IQueryable vs IEnumerable

问题描述 投票:1回答:1

请考虑以下片段:

IQueryable<Person> pQ = from p in db.People select p;
IEnumerable<Person> pE = pQ;

Console.WriteLine(pQ.Count());
Console.WriteLine(pE.Count());

两者都给出相同的结果,但是如果跟踪生成的SQL,则IQueryable版本将使用COUNT发出查询,而IEnumerable版本将仅发出SELECT,拉入所有行并进行计数在内存中,这可能非常低效。同样适用于其他方法,例如Sum()Average(),并且在EF6和EF Core 3中都存在。

原因是Count()是扩展方法,因此绑定到变量的静态类型(在第一种情况下为IQueryable,在第二种情况下为IEnumerable),而不是动态类型(两种情况下都相同) ,因为它是同一个对象)。

这是一个非常令人讨厌的陷阱,这意味着在这种情况下通常最好避免IEnumerable。但是,有一种解决方法:

Console.WriteLine(pE.AsQueryable().Count());

这表示SQL COUNT已发布。

((注:强制转换为IQueryable在这里也可以,但通常不会-如果IEnumerable纯粹是指内存数据,则强制转换将失败,但是AsQueryable()只会将对象包围在中性包装器。)

我的问题是:由于这个问题很容易被忽略,并且会导致这种低效的行为,为什么对AsQueryable()的调用不能简单地嵌入到扩展方法的IEnumerable实现中?

entity-framework linq-to-entities extension-methods
1个回答
0
投票

我的问题是:由于这个问题很容易被忽略并且会导致这种低效的行为,为什么对AsQueryable()的调用不能简单地嵌入到扩展方法的IEnumerable实现中?

© www.soinside.com 2019 - 2024. All rights reserved.