Performance LINQ到实体——OrderBy().ToList()与ToList().OrderBy()的比较
我希望通过以下LINQ表达得到确认/澄清: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); 我认
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的优势(例如,在将集合拉入内存之前过滤/修剪集合)
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方法集
例如:-
话虽如此,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);