Это хорошая практика, чтобы иметь запрос linq в контроллерах? - PullRequest
12 голосов
/ 22 августа 2011

Я не очень знаком с шаблоном MVC. Не могли бы вы сказать мне, какое из следующих трех действий контроллера лучше? Спасибо:)

(1) Есть запрос в действии:

public ActionResult List()
{
   var query = repository.Query().Where(it => it.IsHandled).OrderBy(it => it.Id);
   // ...
}

(2) Есть запрос в обслуживании:

public ActionResult List() 
{
    var items = service.GetHandledItemsOrderById();
    // ...
}

(3) Иметь заказ в действии:

public ActionResult List()
{
    var items = service.GetHandledItems().OrderBy(it => it.Id);
    // ...
}

Если мы выберем (1), тогда у нас слишком много бизнес-логики в контроллере?

Если мы выберем (2), может быть много методов обслуживания, таких как GetXXXByYYY().

Если мы выбираем (3), почему мы инкапсулируем Where(it => it.IsHandled), а не
OrderBy(it => it.Id.

Есть идеи?

Ответы [ 2 ]

4 голосов
/ 22 августа 2011

Я уверен, что мнения могут отличаться, но я научился стараться использовать как можно больше бизнес-логики в сервисе. 3 будет моим выбором. С 1 вы уже заметили проблему. С помощью 2 вы вводите приоритет отображения в сервисе. С 3 вы обрабатываете настройки отображения там, где это необходимо Если вы хотите представить другой интерфейс для вашего бизнес-уровня, вам потребуются потенциально ненужные итерации кода, выбрав 2.

3 голосов
/ 22 августа 2011

Это зависит.:)

Мое мнение:

Мне нравится держать свой сервис свободным, чтобы минимизировать дублирующийся код.Я также фанат труб и фильтров.

Вот что я бы сделал (и СДЕЛАЛ).

Сервис

public ICollection<Item> GetHandledItems<TKey>(OrderingOptions<Item, TKey> orderingOptions) 
{
   return repository
      .Query()
      .WhereHandled()
      .WithOrdering(orderingOptions)
      .ToList();     
}

ItemFilters.cs

public static IQueryable<Item> WhereHandled(this IQueryable<Item> source)
{
   return source.Where(it => it.IsHandled);
}

public static IOrderedQueryable<T> WithOrdering<T, TKey>(
   this IQueryable<T> source,
   OrderingOptions<T, TKey> orderingOptions)
{
   return orderingOptions.SortDescending 
      ? source.OrderByDescending(orderingOptions.OrderingKey) :                                                    
        source.OrderBy(orderingOptions.OrderingKey);
}

OrderingOptions.cs

 public class OrderingOptions<T,TKey>
 {
    public OrderingOptions(Expression<Func<T,TKey>> orderingKey, bool sortDescending = false)
    {
       OrderingKey = orderingKey;
       SortDescending = sortDescending;
    }

    public Expression<Func<T,TKey>> OrderingKey { get; private set; }
    public bool SortDescending { get; private set; }
 }

Таким образом, вы можете указать порядок в контроллере:

var items = service.GetHandledItems(new OrderingOptions(it => it.Id));

Различия между вышеперечисленным и опциями 3:

  • Вышеизложенное материализует последовательность перед возвратом в контроллер.Вариант 3 не делает, что опасно (вы можете в конечном итоге вернуть запрос в View и нарушить шаблон MVC).
  • Универсальный POCO «Упорядочивание», может использоваться где угодно и сохраняет ваши запросы СУХИМ.* Служба становится тупой , и просто смягчает между хранилищем и контроллером (что все, что он должен делать, IMO).Логика (например, фильтры) отводится в одно место.
...