IQueryable和IEnumerable有什么区别


Answers:


186

IEnumerable<T>代表的仅向前光标T。.NET 3.5添加的扩展方法,其中包括的LINQ standard query operatorsWhereFirst,与需要谓词或匿名函数采取任何操作符Func<T>

IQueryable<T>实现相同的LINQ标准查询运算符,但接受Expression<Func<T>>谓词和匿名函数。Expression<T>是一个编译的表达式树,它是该方法的分解版本(如果可以的话,则为“半编译”),可以由查询对象的提供程序进行解析并相应地使用。

例如:

IEnumerable<Person> people = GetEnumerablePeople();
Person person = people.Where(x => x.Age > 18).FirstOrDefault();

IQueryable<Person> people = GetQueryablePeople();
Person person = people.Where(x => x.Age > 18).FirstOrDefault();

在第一个块中,x => x.Age > 18是一个匿名方法(Func<Person, bool>),可以像执行其他任何方法一样执行该方法。Enumerable.Where将为每个人执行一次该方法,并为其yield返回值true

在第二个块中x => x.Age > 18是一个表达式树(Expression<Func<Person, bool>>),可以将其视为“年龄> 18”。

这允许LINQ-to-SQL之类的东西存在,因为它们可以解析表达式树并将其转换为等效的SQL。而且由于提供程序不需要等到IQueryable枚举IEnumerable<T>完后才执行(毕竟实现了),因此它可以结合使用多个查询运算符(在上述示例Where和中FirstOrDefault),以便就如何对基础数据执行整个查询做出更明智的选择。源(如SELECT TOP 1在SQL中使用)。

看到:


1
很简单的答案
ashveli

83

在现实生活中,如果您使用的是像LINQ-to-SQL这样的ORM

  • 如果创建IQueryable,则查询可能会转换为sql并在数据库服务器上运行
  • 如果创建了IEnumerable,则在运行查询之前,所有行都将作为对象拉入内存。

在这两种情况下,如果您不调用a ToList()ToArray()那么每次使用该查询时都会执行一次查询,因此,假设您有一个,IQueryable并从中填充了4个列表框,则查询将对数据库运行4次。

另外,如果您扩展查询:

q.Select(x.name = "a").ToList()

然后使用IQueryable生成的SQL将包含where name = "a",但是使用IEnumerable更多角色将从数据库中撤回,然后x.name = "a"将通过.NET进行检查。


“查询可能转换为sql”:我没有得到“可能是”。另外,如果我有一个IEnumerable并创建一个“复杂链”,那么(显然)与IQueryable不同,它不会转换为“优化的” SQL查询。只想确认当您说“所有行都将被拉入内存”时的含义。让我们说我有两个where子句,然后将实体的所有元组首先提取到内存中,然后进行常规的“内存中”过滤吗?
Vaibhav,2015年

36

“主要区别在于,为IQueryable定义的扩展方法采用Expression对象而不是Func对象,这意味着它接收的委托是表达式树而不是要调用的方法。IEnumerable非常适合使用内存中的集合,但是IQueryable允许用于远程数据源,例如数据库或Web服务”

资料来源:这里


19

IEnumerable IEnumerable最适合用于内存中收集。IEnumerable不会在项目之间移动,它是仅转发集合。

IQueryable IQueryable最适合于远程数据源,例如数据库或Web服务。IQueryable是一项非常强大的功能,可启用各种有趣的延迟执行方案(例如基于分页和基于组合的查询)。

因此,当您只需要简单地遍历内存中的集合时,请使用IEnumerable,如果您需要对集合进行任何操作(如数据集和其他数据源),请使用IQueryable


11

原则上的区别是IEnumerable始终会枚举其所有元素,而IQueryable会根据查询枚举元素,甚至执行其他操作。该查询是一个表达式(.Net代码的数据表示形式),IQueryProvider必须对其进行探索/解释/编译/以任何方式生成结果。

使用查询表达式有两个优点。

第一个优势是优化。由于查询表达式中包含诸如“ Where”之类的修饰符,因此IQueryProvider可以应用原本不可能的优化。提供者可以使用哈希表来查找具有给定键的项,而不是返回所有元素然后由于“ Where”子句而丢弃大多数元素。

第二个优点是灵活性。由于表达式是可探索的数据结构,因此您可以执行诸如序列化查询并将其发送到远程计算机(例如linq-to-sql)之类的事情。



1

首先,在System.Collections命名空间中找到IEnumerable,而在System.Linq命名空间中找到IQueryable。如果在从列表,数组集合等内存中的集合中查询数据时使用IEnumerable,并且从内存(例如远程数据库,服务)集合中查询数据时使用IEnumerable,则可以使用IQueryable。因为从数据库查询数据时,IEnumerable在服务器端执行select查询,因此在客户端将数据加载到内存中,然后筛选数据。因此需要做更多的工作,并且变得缓慢。从数据库查询数据时,IQueryable使用所有过滤器在服务器端执行选择查询。因此,工作量少,速度快。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.