使用 OrderBy 优化 Lambda Linq to SQL 查询

发布于 2024-09-08 10:24:56 字数 771 浏览 2 评论 0原文

我有以下 lambda 表达式:

IEnumerable<Order> query
       = _ordersRepository.GetAllByFilter(
            o => 
                o.OrderStatus.OrderByDescending(os => os.Status.Date).First()
                    .Status.StatusType.DisplayName != "Completed"
                ||   
                o.OrderStatus.OrderByDescending(os => os.Status.Date).First()
                    .Status.Date > sinceDate
         ).OrderBy(o => o.DueDate);

如您所见,我必须在主查询中对集合进行两次排序(总共三次)才能执行 OR 查询。

1)查询优化器是否足够聪明,能够有效地处理这个问题?

2)如果不是,我怎样才能重写这个表达式只排序一次,但保持lambda语法

这链接到上一个问题,它解释了查询如果上面的代码不清楚,请更详细地说明。

I have the following lambda expression:

IEnumerable<Order> query
       = _ordersRepository.GetAllByFilter(
            o => 
                o.OrderStatus.OrderByDescending(os => os.Status.Date).First()
                    .Status.StatusType.DisplayName != "Completed"
                ||   
                o.OrderStatus.OrderByDescending(os => os.Status.Date).First()
                    .Status.Date > sinceDate
         ).OrderBy(o => o.DueDate);

As you can see, I'm having to order the collection twice within the main query (so three times in total) in order to perform my OR query.

1) Is the query optimiser clever enough to deal with this in an efficient way?

2) If not, how can I rewrite this expression to only order by once, but keeping with lambda syntax?

This is linked to this previous question, which explains the query in a bit more detail if the above code isn't clear.

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

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

发布评论

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

评论(2

莫多说 2024-09-15 10:24:56

1)查询优化器是否足够聪明,能够有效地处理这个问题?

您可以获取此查询的 SQL(一种方法是使用 SQL 探查器),然后向 SQL Studio 询问执行计划。除非你这样做,否则无法知道优化器的想法。我的猜测是答案是“不”。

2) 如果不是,我怎样才能重写这个表达式,使其只按一次排序,但又保持 lambda 语法?

像这样:

IEnumerable<Order> query = _ordersRepository.GetAllByFilter( o =>
  o.OrderStatus
    .OrderByDescending(os => os.Status.Date)
    .Take(1)
    .Any(os => os.Status.StatusType.DisplayName != "Completed"
      || os.Status.Date > sinceDate)
})
.OrderBy(o => o.DueDate); 

1) Is the query optimiser clever enough to deal with this in an efficient way?

You can get the SQL for this query (one way is to use the SQL profiler), and then ask SQL Studio for the execution plan. Unless you do this, there is no way to know what the optimizer thinks. My guess is the answer is "no".

2) If not, how can I rewrite this expression to only order by once, but keeping with lambda syntax?

Like this:

IEnumerable<Order> query = _ordersRepository.GetAllByFilter( o =>
  o.OrderStatus
    .OrderByDescending(os => os.Status.Date)
    .Take(1)
    .Any(os => os.Status.StatusType.DisplayName != "Completed"
      || os.Status.Date > sinceDate)
})
.OrderBy(o => o.DueDate); 
沙沙粒小 2024-09-15 10:24:56

关于第一点:您可以看到通过订阅 DatabaseContext 对象的输出生成的 SQL。这通常位于名为 Log 的属性中。

至于优化您的查询,请尝试以下操作(我没有测试过,所以我不知道它是否会起作用)

IEnumerable<Order> query
   = _ordersRepository.GetAllByFilter(
        o =>
            o.OrderStatus.Max(os => os.Status.Date).Any(os =>
                os.Status.StatusType.DisplayName != "Completed"
                || os.Status.Date > sinceDate)
     ).OrderBy(o => o.DueDate);

希望这只会执行一次子查询,并且还执行 max 而不是 top 1 的 order by 。

Regarding your first point: You can see the SQL that is generated by subscribing to the output of the DatabaseContext object. This is usually in a property called Log.

As for optimising your query, try the following (I've not tested it so I don't know if it will work)

IEnumerable<Order> query
   = _ordersRepository.GetAllByFilter(
        o =>
            o.OrderStatus.Max(os => os.Status.Date).Any(os =>
                os.Status.StatusType.DisplayName != "Completed"
                || os.Status.Date > sinceDate)
     ).OrderBy(o => o.DueDate);

Hopefully that will only perform the subquery once, and also performs a max rather than an order by with top 1.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文