过滤内存中的集合:IQueryable能否提供更好的性能?

时间:2014-03-12 19:05:26

标签: c# performance entity-framework ienumerable iqueryable

假设我有一个内存集合(人),我必须在其中应用一些过滤条件。

var distinctproductKeys = persons.Where(d => d.productsDictionary != null)
                                 .SelectMany(d => d.productsDictionary.Keys)
                                 .Distinct();

VS。如果我在应用过滤器之前使用IQueryable

var distinctproductKeys = persons.AsQueryable()
                                 .Where(d => d.productsDictionary != null)
                                 .SelectMany(d => d.productsDictionary.Keys)
                                 .Distinct();

我已经读过,一旦你的集合在内存中,IQueryable和IEnumerable都会提供相同的性能。但是运行这两个查询我观察到的IQueryable版本更快。有人可以告诉我为什么吗?

1 个答案:

答案 0 :(得分:2)

我不知道你是如何测试你的表现但是在使用 IQueryable IEnumerable 时要记住的主要事情是两者都会给你延迟执行

区别是IQueryable是允许LINQ-to-SQL(LINQ.-to-anything真正)工作的接口。因此,如果您在IQueryable上进一步优化查询,则该查询将在数据库中执行,如果可能的话。

对于IEnumerable情况,它将是LINQ-to-object,这意味着必须将与原始查询匹配的所有对象从数据库加载到内存中。

在代码中:

IQueryable<Customer> custs = ...;
// Later on...
var goldCustomers = custs.Where(c => c.IsGold);

该代码将执行SQL以仅选择黄金客户。另一方面,以下代码将在数据库中执行原始查询,然后过滤掉内存中的非黄金客户:

IEnumerable<Customer> custs = ...;
// Later on...
var goldCustomers = custs.Where(c => c.IsGold);

这是一个非常重要的区别,在许多情况下,使用IQueryable可以避免从数据库中返回太多行。另一个主要的例子是进行分页:如果你在IQueryable上使用Take和Skip,你将只获得所请求的行数;在IEnumerable上执行此操作将导致所有行都加载到内存中。