【问题标题】:LINQ to Entities -- OrderBy().ToList() vs. ToList().OrderBy()LINQ to Entities -- OrderBy().ToList() 与 ToList().OrderBy()
【发布时间】:2012-12-11 19:22:33
【问题描述】:

我正在寻找这些 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);
  1. 我认为第一种方法是 LINQ to Entities 是否正确,其中 EF 构建了一个更具体的 SQL 语句以传递,将排序工作放在数据库上?

  2. 第二种方法LINQ to Objects 是不是 LINQ 在排序之前将整个集合拖到内存中(ToList() 枚举?),从而将负担留给服务器端(本例中为 Web 服务器)?

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

  3. 但是我是否应该注意其他任何细节/权衡,或者“方法 2”可能优于第一种方法的时间?

更新:

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

【问题讨论】:

    标签: performance linq entity-framework linq-to-entities


    【解决方案1】:
    1. 是的。
    2. 是的。
    3. 是的。

    您是正确的,调用 ToList() 会强制 linq-to-entities 评估并以列表形式返回结果。正如您所怀疑的,这可能会对性能产生巨大影响。

    在某些情况下,linq-to-entities 无法弄清楚如何解析看似非常简单的查询(例如 Where(x => SomeFunction(x)))。在这些情况下,您通常别无选择,只能调用 ToList() 并对内存中的集合进行操作。


    响应您的更新:

    ToList() 总是强制它前面的所有内容立即评估,而不是延迟执行。举个例子:

    someEnumerable.Take(10).ToList();
    

    对

    someEnumerable.ToList().Take(10);
    

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

    【讨论】:

    • 谢谢。你能看到我的更新,更重要的是上面对 D Stanly 回答的评论吗?
    • @JonB:您能否对此进行更多说明:“在某些情况下,linq-to-entities 无法弄清楚如何解析看起来非常简单的查询(例如 Where(x => SomeFunction (x)))."?
    • @Pawel Equals() 是想到的一种方法,LINQ to ENTITIES 将其转换为 LINQ to SQL 语句。
    • @Pawel,JonB。谢谢。正是需要的。虽然我也喜欢Equals() 或类似翻译问题的示例。
    • @JonB - 我很难理解你的评论。你的意思是 Sql 而不是 Linq to Sql?您能否更具体地了解 Equals - 我尝试了以下方法 - 只要我有正确的类型 - 它就可以工作:var s = ctx.tasks.Where(t => t.task_id.Equals(Guid.NewGuid())).ToList();
    【解决方案2】:

    我认为第一种方法是 LINQ to Entities 是否正确,其中 EF 构建了一个更具体的 SQL 语句以传递,将排序工作放在数据库上?

    是的

    第二种方法是 LINQ to Objects,其中 LINQ 在排序之前将整个集合拖到内存中...从而将负担留给服务器端...?

    是的

    但是我是否应该注意其他任何细节/权衡,或者“方法 2”可能优于第一种方法的时间?

    很多时候方法 1 是不可能的 - 通常是当您有一个复杂的过滤器或排序顺序无法直接转换为 SQL 时(或者更合适的是,EF 不支持直接 SQL 转换)。此外,由于您无法通过网络传输延迟加载的 IQueryables,因此无论何时您必须序列化结果,您都必须首先使用 ToList() 或类似的东西来实现它。

    【讨论】:

    • 我想你也刚刚回答了我的更新——在源只实现 IEnumerable 的情况下,这些语句本质上没有什么不同?
    • 不一定; IEnumerable<T> 也可以以惰性方式实现。
    【解决方案3】:

    需要注意的另一件事是,IQueryable 不保证 (a) 底层提供者的语义推理,或 (b) 提供者实现了多少 IQueryable 方法集。

    例如:-

    1. EF 不支持 Last()。
    2. 也不支持将日期时间与有效 T-SQL 进行时间部分比较。
    3. 不支持子查询中的 FirstOrDefault()。

    在这种情况下,您需要将数据带回客户端,然后在客户端执行进一步的评估。

    您还需要了解它“如何”解析 LINQ 管道以生成(在 EF 的情况下)T-SQL。因此,有时您必须仔细考虑如何构建 LINQ 查询才能生成有效的 T-SQL。

    话虽如此,IQueryable 是 .NET 框架中非常强大的工具,非常值得更加熟悉。

    【讨论】:

      猜你喜欢
      • 2016-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多