在控制器中使用linq查询是一种好习惯吗?

时间:2011-08-22 02:03:09

标签: asp.net-mvc model-view-controller controller business-logic

我对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 个答案:

答案 0 :(得分:4)

我确信意见可能会有所不同,但我已经学会了尽可能多地保留服务中的业务逻辑。 3将是我的选择。有了1,你已经发现了这个问题。使用2,您将在服务中引入显示优先级。使用3,您可以在必要时处理显示首选项。如果要为业务层引入另一个接口,则需要选择2来进行潜在的,不必要的代码迭代。

答案 1 :(得分:3)

取决于。 :)

我的意见:

我喜欢保持我的服务松散,以尽量减少重复的代码。我也是管道和过滤器的粉丝。

这就是我要做的事(和做的事)。

<强>服务

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; }
 }

这样,您可以在Controller中指定顺序:

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

以上与选项3之间的差异:

  • 上面在返回Controller之前实现序列。选项3没有,这是危险的(你可能最终将查询返回到View并打破MVC模式)。
  • 通用“订购”POCO,可在任何地方使用并保留您的查询D-R-Y。
  • 服务变得,只是存储库和控制器之间的缓解器(它应该做的就是IMO)。逻辑(例如过滤器)抽象到一个地方。