LINQ to Entities - OrderBy().ToLisT()与ToList().OrderBy()

one*_*mer 7 linq performance linq-to-entities entity-framework

我正在寻找这些LINQ表达式的确认/澄清:

var context = new SomeCustomDbContext()

// LINQ to Entities?
var items  = context.CustomItems.OrderBy(i => i.Property).ToList();

// LINQ to Objects?
var items2 = context.CustomItems.ToList().OrderBy(i => i.Property);
Run Code Online (Sandbox Code Playgroud)

(Q1)我是否认为第一种方法是LINQ to EntitiesEF构建一个更具体的SQL语句来传递,将订购工作放在数据库上?

(Q2)第二种方法LINQ to Objects是LINQ ToList()在订购之前将整个集合拖入内存(枚举?),从而在服务器端(本例中为Web服务器)留下负担?

如果是这种情况,我可以很快看到L2E有利的情况(例如,在将它们拉入内存之前过滤/修剪集合).

(Q3)但是,我应该注意还有其他任何细节/权衡,或者"方法2"可能比第一种方法更有利的时候?

更新:

假设我们没有使用EntityFramework,只要底层存储库/数据源实现IQueryable<T>正确,这仍然是正确的?如果不是这两个语句都导致LINQ to Objects内存中的操作?

Jon*_*n B 9

  1. 是.
  2. 是.
  3. 是.

你是正确的,调用ToList()迫使linq-to-entities评估并将结果作为列表返回.正如您所怀疑的那样,这可能会产生巨大的性能影响.

在某些情况下,linq-to-entities无法弄清楚如何解析看起来像一个非常简单的查询(如Where(x => SomeFunction(x))).在这些情况下,您通常别无选择ToList(),只能在内存中调用和操作集合.


为了回应您的更新:

ToList()总是迫使一切都在它前面立即评估,而不是延迟执行.举个例子:

someEnumerable.Take(10).ToList();
Run Code Online (Sandbox Code Playgroud)

VS

someEnumerable.ToList().Take(10);
Run Code Online (Sandbox Code Playgroud)

在第二个示例中,someEnumerable必须在获取前10个元素之前执行任何延迟的工作.如果someEnumerable正在做一些劳动密集型工作(比如从磁盘读取文件Directory.EnumerateFiles()),这可能会产生非常实际的性能影响.