Performance LINQ到实体——OrderBy().ToList()与ToList().OrderBy()的比较

Performance LINQ到实体——OrderBy().ToList()与ToList().OrderBy()的比较,performance,linq,entity-framework,linq-to-entities,Performance,Linq,Entity Framework,Linq To Entities,我希望通过以下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); 我认

我希望通过以下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);
  • 我认为第一种方法是
    LINQ to Entities
    ,其中EF构建了一个更具体的SQL语句来传递,将排序工作放在数据库上,这对吗

  • 第二种方法是
    LINQ-to-Objects
    ,其中LINQ在排序之前将整个集合拖到内存中(即
    ToList()
    枚举?),从而将负担留给服务器端(本例中的web服务器)

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

  • 但是,我是否应该知道其他细节/权衡,或者“方法2”比第一种方法更有利的时候

  • 更新:

    假设我们没有使用EntityFramework,只要底层存储库/数据源实现
    IQueryable
    就仍然如此,对吗?如果这两条语句没有在内存中导致
    LINQ to Objects
    操作

  • 调用
    ToList()
    会强制linq对实体求值并将结果作为列表返回,这是正确的。正如您所怀疑的,这可能会对性能产生巨大影响

    在某些情况下,LINQto实体无法理解如何解析看起来非常简单的查询(如
    where(x=>SomeFunction(x))
    )。在这些情况下,您通常别无选择,只能调用
    ToList()
    并对内存中的集合进行操作


    针对您的更新:

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

    someEnumerable.Take(10).ToList();
    
    vs

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

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

    第二种方法是LINQ到对象,其中LINQ将整个集合拖到内存中。。。在订购之前,将负担留给服务器端

    但是,我是否应该知道其他细节/权衡,或者“方法2”比第一种方法更有利的时候


    在很多情况下,方法1是不可能的-通常是当您有一个复杂的筛选器或排序顺序,无法直接转换为SQL时(或者更恰当地说,在EF不支持直接SQL转换的情况下)。另外,由于您不能通过线路传输延迟加载的
    IQueryable
    s,因此任何时候您必须序列化一个结果,您必须首先使用
    ToList()
    或类似的东西来具体化它。

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

    例如:-

  • EF不支持Last()
  • 它也不支持将日期时间的时间部分比较到有效的T-SQL中
  • 它在子查询中不支持FirstOrDefault()
  • 在这种情况下,您需要将数据带回客户端,然后在客户端执行进一步的评估

    您还需要了解它如何解析LINQ管道以生成(对于EF)T-SQL。因此,为了生成有效的T-SQL,有时必须仔细考虑如何构造LINQ查询


    话虽如此,IQueryable在.NET框架中是一个非常强大的工具,值得更多地了解。

    我想你也回答了我的更新——如果源代码只实现IEnumerable,那么这些语句本质上没有什么不同?不一定
    IEnumerable
    也可以以惰性方式实现。谢谢。你能看到我的更新吗?更重要的是,你能解释一下吗?@JonB:你能不能说得更清楚一些:“在有些情况下,linq to entities无法解析看起来非常简单的查询(比如where(x=>SomeFunction(x))。”?@Pawel Equals()是我想到的一个方法,哪个LINQ to实体将其转换为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()
    
    someEnumerable.ToList().Take(10);