IQueryable 和 IEnumable 的区别是什么

我搞不懂这有什么区别。刚接触。Net,我知道我可以使用 Linq 扩展查询 IEnumerables。那么这个 IQueryable是什么,它有什么不同呢?


另请参阅与此问题重叠的 IQueryable [ T ]和 IEnumable [ T ]的区别是什么?

100006 次浏览

IQueriable 与 IEnumable 相同,但它还提供了用 Linq 实现自定义查询的附加功能。这是 MSDN 上的描述: http://msdn.microsoft.com/en-us/library/system.linq.iqueryable.aspx

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

资料来源: 给你

IEnumerable<T>表示 T的仅向前游标。.NET 3.5添加了包含 LINQ standard query operators的扩展方法,如 WhereFirst,任何需要谓词或匿名函数的操作符都采用 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将为每个人执行一次该方法,yielding 值是该方法返回的 true值。

在第二个块中,x => x.Age > 18是一个表达式树(Expression<Func<Person, bool>>) ,可以认为它是“ is the‘ Age’property > 18”。

这允许 LINQ-to-SQL 之类的东西存在,因为它们可以解析表达式树并将其转换为等效的 SQL。因为提供程序在枚举 IQueryable之前不需要执行(毕竟它实现了 IEnumerable<T>) ,所以它可以组合多个查询操作符(在上面的例子 WhereFirstOrDefault中)来对如何对底层数据源执行整个查询做出更明智的选择(比如在 SQL 中使用 SELECT TOP 1)。

参见:

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

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

在这两种情况下,如果你不调用 ToList()或者 ToArray(),那么每次使用它的时候查询都会被执行,比如说,你有一个 IQueryable并且你从中填充了4个列表框,那么这个查询将对数据库运行4次。

此外,如果您扩展您的查询:

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

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

主要区别在于 IEnumable 将始终枚举其所有元素,而 IQueryable 将基于查询枚举元素,甚至执行其他操作。查询是一个 Expression (表达式的数据表示形式。Net 代码) ,IQueryProvider 必须探索/解释/编译/其他方法才能生成结果。

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

第一个优势是优化。因为查询表达式中包含“ Where”等修饰符,所以 IQueryProvider 可以应用其他不可能的优化。提供程序可以使用哈希表来定位具有给定键的项,而不是返回所有元素,然后由于“ Where”子句而丢弃大部分元素。

第二个优势是灵活性。因为表达式是可探索的数据结构,所以可以对查询进行序列化并将其发送到远程计算机(例如 linq-to-sql)。

数不胜数 IEnumable 最适合处理内存中的收集。 IEnumable 不在项之间移动,它只是向前集合。

我有疑问 IQueryable 最适合远程数据源,如数据库或 Web 服务。 IQueryable 是一个非常强大的特性,它支持各种有趣的延迟执行场景(比如分页和基于组合的查询)。

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