我正在寻找以下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将是有利的情况(例如。在将集合拖入内存之前对它们进行筛选/修剪)。更新:
假设我们没有使用EntityFramework,只要底层存储库/数据源实现IQueryable<T>
,这仍然是正确的,对吗?如果不是,这两条语句都会导致内存中的LINQ to Objects
操作?
发布于 2012-12-11 19:27:23
正确的是,调用ToList()
会迫使linq到实体计算结果并将其作为列表返回。正如您所怀疑的,这可能会带来巨大的性能影响。
在有些情况下,linq到实体无法解析看起来非常简单的查询(如Where(x => SomeFunction(x))
)。在这些情况下,您通常别无选择,只能调用ToList()
并对内存中的集合进行操作。
针对您的最新情况:
ToList()
总是强迫它前面的所有东西立即评估,而不是延迟执行。举个例子:
someEnumerable.Take(10).ToList();
vs
someEnumerable.ToList().Take(10);
在第二个示例中,在使用前10个元素之前,必须执行对someEnumerable
的任何延迟工作。如果someEnumerable
正在做一些劳动强度很大的事情(比如使用Directory.EnumerateFiles()
从磁盘读取文件),这可能会产生非常真实的性能影响。
发布于 2012-12-11 19:28:17
我是否正确地认为第一种方法是LINQ实体,其中EF构建了要传递的更具体的SQL语句,将排序工作放在数据库上?
是
是LINQ对象的第二个方法,其中LINQ将整个集合拖到内存中.在订购之前把负担留给服务器端.?
是
但是,我是否应该知道其他的细节/权衡,或者“方法2”可能比第一种方法更有利的时候?
在很多情况下,方法1是不可能的--通常是当您有一个不能直接转换为SQL的复杂筛选器或排序顺序时(或者更合适的情况下,EF不支持直接SQL转换)。另外,由于不能通过线路传输延迟加载的IQueryable
,所以任何时候必须序列化结果时,都必须首先用ToList()
或类似的方法来实现它。
发布于 2012-12-11 20:02:04
需要注意的另一件事是,IQueryable不能保证(a)底层提供者的语义推理,或者(b)提供者实现了多少IQueryable方法。
例如:-
在这种情况下,您需要将数据带回客户端,然后执行客户端的进一步评估。
您还需要了解它如何解析LINQ管道以生成(在EF情况下)T。因此,有时您必须仔细考虑如何构造LINQ查询,以便生成有效的T。
尽管如此,IQueryable<>在.NET框架中是一个非常强大的工具,值得更多地熟悉。
https://stackoverflow.com/questions/13827004
复制相似问题