IQueryable和IEnumerable之间有什么区别

时间:2010-03-12 14:22:40

标签: linq ienumerable iqueryable .net-3.0

我对这种差异感到困惑。作为.Net的新手,我知道我可以使用Linq扩展来查询IEnumerables。那么IQueryable是什么?它有何不同?


另请参阅与此问题重叠的What is the difference between IQueryable[T] and IEnumerable[T]?

7 个答案:

答案 0 :(得分:182)

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将为每个人执行一次该方法,yield方法返回的值为true

在第二个区块中,x => x.Age > 18是一个表达式树(Expression<Func<Person, bool>>),可以将其视为“是'Age'属性&gt; 18”。

这允许存在LINQ-to-SQL之类的东西,因为它们可以解析表达式树并将其转换为等效的SQL。并且因为提供者在枚举IQueryable之前不需要执行(毕竟它实现了IEnumerable<T>),它可以组合多个查询运算符(在上面的例子中Where和{ {1}})更明智地选择如何针对底层数据源执行整个查询(比如在SQL中使用FirstOrDefault)。

请参阅:

答案 1 :(得分:77)

在现实生活中,如果你正在使用像LINQ-to-SQL那样的ORM

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

在这两种情况下,如果您不拨打ToList()ToArray(),则每次使用时都会执行查询,因此,您有IQueryable并填写从中查找4个列表框,然后查询将对数据库运行4次。

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

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

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

答案 2 :(得分:35)

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

来源:here

答案 3 :(得分:17)

<强>的IEnumerable IEnumerable最适合使用内存中的集合。 IEnumerable不会在项目之间移动,它只是前向收集。

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

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

答案 4 :(得分:9)

主要区别在于IEnumerable将始终枚举其所有元素,而IEqueryable将根据查询枚举元素,甚至执行其他操作。查询是一个Expression(.Net代码的数据表示),IQueryProvider必须探索/解释/编译/以生成结果。

拥有查询表达式有两个好处。

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

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

答案 5 :(得分:1)

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

答案 6 :(得分:1)

首先,在System.Collections命名空间中找到IEnumerable,而在System.Linq命名空间中找到IQueryable。如果您在查询内存集合(如List,Array集合等)中的数据时使用IEnumerable,并在从外部存储器(如远程数据库,服务)集合中查询数据时使用IQueryable。因为在从数据库查询数据时,IEnumerable在服务器端执行select查询,在客户端加载内存中的数据然后过滤数据。因此,做更多的工作,变得缓慢。在从数据库查询数据时,IQueryable在服务器端使用所有过滤器执行select查询。因此,工作量减少,变得快速。