【问题标题】:difference of calling OrderBy() before Where() and vice versa在 Where() 之前调用 OrderBy() 的区别,反之亦然
【发布时间】:2013-03-15 11:01:32
【问题描述】:

我想知道...在我的应用程序中,我正在做这样的事情:

var threads = scykDb.Threads
                    .AsQueryable()
                    .Where(condition)
                    .OrderByDescending(t => t.DateCreated)
                    .Skip(threadsToSkip)
                    .Take(threadsPerPage)
                    .Select(t => t)
                    .ToList();

如果我在 Where() 之前执行 OrderBy() 会发生什么?重要吗?skip() 或 take() 怎么样,这些位置也重要吗?

var threads = scykDb.Threads
                    .AsQueryable()
                    .OrderByDescending(t => t.DateCreated)
                    .Where(condition)
                    .Skip(threadsToSkip)
                    .Take(threadsPerPage)
                    .Select(t => t)
                    .ToList();

【问题讨论】:

  • 我也想知道。试试看。看看会发生什么。
  • @Dan 为什么要避免ToList()
  • Linq 有一个延迟执行,它会尽可能晚地发生,以便立即在树中评估所有表达式。顺序应该无关紧要。
  • @Dan,你需要 .ToList() 来实际 download 数据库中的数据。我不知道它是如何工作的,但在我调用 .ToList() threads 之前只是一个查询,而不是数据。
  • OP,当您迭代查询时(例如在 foreach 循环中),您将调用它并具体化数据库中的结果,因此 ToList() 不是严格必要的。也就是说,在存储库中以可预测的方式强制它是我选择做的事情。当您想要延迟执行时,Dan 的建议是有效的,但有时您根本不想要。

标签: c# linq ado.net


【解决方案1】:

如果您的查询实际上是通过实体框架、Linq-to-SQL 或其他此类提供程序针对数据库,那么您示例中的调用顺序无关紧要。

如果这是针对内存中的集合发生的,则您是在过滤之前排序,这比首先应用过滤器不太理想。例如,您正在订购可能只是丢弃的元素。 (排序涉及相对大量的工作。过滤首先减少了这项工作。)

也就是说,即使与数据库相反,我也会支持第二种形式,因为相同的代码对于内存查询同样有效,所以要养成在数据库中编写代码的习惯通常理想的方式。也有争议的是,您期望在订购之前将过滤视为一个思考过程。

【讨论】:

  • 我注意到,当然可以编写一个 Linq-to-objects 的实现来检测 orderby 之后何时发生,并像数据库一样优化工作流程。实现实际上并没有这样做,但这是可能的。 Linq-to-objects 的实现确实对 where 和 select 子句进行了一些小的重组,以使它们在常见情况下更有效。
  • 你有没有写过关于这个 Where/Select 重组的博客?我会很好奇它会做什么、为什么以及何时会这样做,它如何影响或避免具有副作用的方法(匿名或其他方式)等。
  • 我没有,但 Jon 有(我提供了少量意见)。 msmvps.com/blogs/jon_skeet/archive/2011/06/16/…——影响是在大多数情况下提高性能,正如 Jon 指出的那样,在某些病理情况下会使情况变得更糟。重排不应该引起语义变化。
  • 谢谢。我会在我丰富的业余时间潜入 Jon 的博客。
猜你喜欢
  • 2012-10-23
  • 1970-01-01
  • 1970-01-01
  • 2011-07-29
  • 1970-01-01
  • 2011-08-18
  • 2014-11-08
  • 2012-02-16
  • 2013-08-16
相关资源
最近更新 更多