2016-03-09 2 views
0

У меня довольно сложный прецедент, который требует выполнения одних и тех же 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(), и назвав его безоговорочно от бизнес-логики, но это так же плохо, как и мое текущее решение, потому что он требует моего бизнес-логику, чтобы знать, как те, методы работают внутри страны.

ответ

1

ForRetailerBase, FromRetailer смотрит на меня как на то, что бизнес-логика не должна знать вообще. Это похоже на помощники запросов, которые должны обрабатываться репозиторием запросов.

Такой репозиторий будет раскрывать методы запроса для бизнеса, методы, которые будут внутренне вызывать ваши ForRetailerBase или FromRetailer по мере необходимости.

Таким образом, вашему бизнесу не понадобятся знания о том, как создавать ваши запросы, и ваша логика запросов будет по-прежнему факторизоваться внутри репозитория.

Боковое примечание: ваш вопрос действительно не связан с конкретными технологиями, которые вы используете. Это больше похоже на вопрос дизайна кода. Может быть, вам стоит задать вопрос по адресу https://softwareengineering.stackexchange.com/, который предназначен для таких вопросов (см. Его on topic page).