У меня довольно сложный прецедент, который требует выполнения одних и тех же SQL-задач условно в разных частях кода. Я хотел дублировать как можно меньше кода, поэтому я создал несколько статических вспомогательных методов, которые позволяют мне добавлять некоторые операторы JOIN, когда это необходимо.QueryOver - обеспечить добавление таблицы соединений только один раз
Я знаю, что это, вероятно, возможно, было сделано немного более чисто с расширениями, но сейчас мой код выглядит примерно так:
static class Foo
{
// Actually adds some filters which need additional JOINs
public static IQueryOver<Transaction, Transaction> FromRetailer(Retailer retailer, IQueryOver<Transaction, Transaction> baseQuery = null)
{
RetailLocation retailLocation = null;
return ForRetailerBase(baseQuery)
.Where(t => retailLocation.Retailer == retailer);
}
// Auxiliary method which only adds some JOINs needed in various places
public static IQueryOver<Transaction, Transaction> ForRetailerBase(IQueryOver<Transaction, Transaction> baseQuery = null)
{
if (baseQuery == null)
baseQuery = QueryOver(); // Custom method that creates a vanilla IQueryOver instance
// Add all sorts of JOINs needed to query the retailer
return baseQuery
.JoinAlias(...)
.Left.JoinAlias(...)
// and so on
;
}
}
В бизнес-логике, я либо должен фактически фильтровать по розничной (в этом случае я звоню FromRetailer()
, который вызывает у меня ForRetailerBase()
), или мне не нужно фильтровать розничный торговец, но мне все еще нужны СОЕДИНЕНИЯ, добавленные ForRetailerBase()
позже для группировки. Вызов ForRetailerBase()
безоговорочно, очевидно, разрывает ситуацию, когда также вызывается FromRetailer()
.
В настоящее время я решаю это очень неуклюже, используя логическую логику в бизнес-логике, чтобы выполнить условие ForRetailerBase()
условно, только если FromRetailer()
не выполнен.
Я понимаю, что это может быть закреплен на двух уровнях: либо использовать более адекватную картину в целом, или добавить их JOIN и условно в ForRetailerBase()
путем допрашивать baseQuery
объекта для определения того, есть ли это необходимым объединения. Я бы предпочел использовать первый подход, если он доступен (эта часть кода все еще относительно молода, и я могу легко ее реорганизовать), но я соглашусь и на второй подход. Проблема в том, что я не знаю, как продвигаться в любом направлении.
Я также понимаю, поверхностное решение, чтобы удалить вызов ForRetailerBase()
из метода FromRetailer()
, и назвав его безоговорочно от бизнес-логики, но это так же плохо, как и мое текущее решение, потому что он требует моего бизнес-логику, чтобы знать, как те, методы работают внутри страны.