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

发布于 2024-11-30 14:30:01 字数 795 浏览 2 评论 0原文

我对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

有什么想法吗?

I'm not very familiar with the MVC pattern. Could you tell me which one of the following three controller actions is better? Thanks :)

(1) Have query in action:

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

(2) Have query in service:

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

(3) Have order by in action:

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

If we choose (1), then we have too much business logic in controller?

If we choose (2), there might be lots of service methods like GetXXXByYYY().

If we choose (3), why we encapsulate Where(it => it.IsHandled) but not
OrderBy(it => it.Id.

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

豆芽 2024-12-07 14:30:01

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

I'm sure opinions may vary, but I've learned to try to keep as much business logic in the service as you can. 3 would be my choice. With 1, you've already spotted the issue. With 2, you are introducing display precedence in a service. With 3, you handle display preferences where necessary. If you were to introduce another interface to your business layer, you are requiring potentially, unnecessary code iterations by choosing 2.

故事和酒 2024-12-07 14:30:01

这要看情况。 :)

我的观点:

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

这就是我要做的(并且确实要做的)。

Service

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)。逻辑(例如过滤器)抽象到一处。

It depends. :)

My opinion:

I like to keep my service loose, to minimize duplicate code. I'm also a fan of pipes and filters.

Here's what i'd do (and DO do).

Service

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

This way, you can specify the ordering in the Controller:

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

Differences between the above and options 3:

  • Above materializes sequence before returning to Controller. Option 3 does not, which is dangerous (you could end up returning query to View and break MVC pattern).
  • Generic "Ordering" POCO, can be used anywhere and keeps your queries D-R-Y.
  • Service becomes dumb, and simply a mitigator between the Repository and the Controller (which is all it should do, IMO). Logic (e.g filters) abstracted to one place.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文