关于linq:iqueryable和ienumerable有什么区别?

What's the difference between IQueryable and IEnumerable

我对两者的区别感到困惑。由于对.NET比较陌生,我知道我可以使用LINQ扩展来查询IEnumerables。那么这个IQueryable是什么?它有什么区别?

还有,iqueryable[t]和IEnumerable[t]之间的区别是什么?这与这个问题重叠。


IEnumerable表示T的仅向前光标。.NET 3.5添加了扩展方法,其中包括LINQ standard query operators,如WhereFirst,任何需要谓词或匿名函数的运算符都使用Func

IQueryable实现相同的linq标准查询运算符,但接受Expression>用于谓词和匿名函数。Expression是一个已编译的表达式树,是一个方法的分解版本("半编译"如果您愿意的话),它可以由可查询的提供者解析并相应地使用。

例如:

1
2
3
4
5
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),可以像其他方法一样执行。Enumerable.Where将对每个人执行一次方法,方法返回trueyielding值。

在第二个块中,x => x.Age > 18是一个表达式树(Expression>可以被认为是"年龄"属性>18"。

这允许像LINQ to SQL这样的东西存在,因为它们可以解析表达式树并将其转换为等效的SQL。而且,由于提供者在枚举IQueryable之前不需要执行(毕竟它实现了IEnumerable),因此它可以组合多个查询运算符(在上面的示例中,WhereFirstOrDefault),以便在如何对基础数据源执行整个查询(如在SQL)。

见:

  • .NET标准查询运算符

在现实生活中,如果使用像linq to sql这样的ORM

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

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

另外,如果扩展查询:

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

然后,使用IQueryable生成的SQL将包含where name ="a",但使用IEnumerable将从数据库中提取更多的角色,然后由.net执行x.name ="a"检查。


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

来源:这里


可枚举的IEnumerable最适合使用内存中的集合。IEnumerable不在项之间移动,它是仅转发的集合。

可查询的iQuery最适合远程数据源,如数据库或Web服务。iQueryable是一个非常强大的功能,它支持各种有趣的延迟执行场景(如分页和基于组合的查询)。

因此,当必须简单地迭代内存中的集合时,请使用IEnumerable,如果需要对集合(如数据集和其他数据源)执行任何操作,请使用iQuery


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

拥有一个查询表达式有两个优点。

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

第二个优势是灵活性。因为表达式是可探索的数据结构,所以您可以执行一些操作,比如序列化查询并将其发送到远程计算机(例如Linq to SQL)。


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


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