IQueryable<T>IEnumerable<T>之间有什么区别?


另请参见与此问题重叠的IQueryable和IEnumerable之间的区别。

#1 楼

首先,IQueryable<T>扩展了IEnumerable<T>接口,因此您可以使用“普通” IEnumerable<T>进行任何操作,也可以使用IQueryable<T>进行处理。

IEnumerable<T>仅有一个GetEnumerator()方法,该方法返回一个Enumerator<T>,您可以为其调用MoveNext()方法以遍历T序列。特别是两个属性-一个属性指向查询提供程序(例如LINQ to SQL提供程序),另一个属性指向将IQueryable<T>对象表示为可被给定查询理解的运行时可遍历抽象语法树的查询表达式提供程序(在大多数情况下,不能将LINQ to SQL表达式提供给LINQ to Entities提供程序)。

该表达式可以只是对象本身的常量表达式或由查询运算符和操作数组成的更复杂的树。调用查询提供程序的IEnumerable<T>IQueryable<T>方法并传递一个表达式,然后分别返回查询结果或另一个IQueryProvider.Execute()

评论


使用AsQueryable有什么好处?

–乔丹
2012-2-23在17:24

唯一的好处就是方便。 AsQueryable()只会将可枚举转换为可查询的对象,如果实现IQueryable接口,则将其返回,否则将其包装在ConstantExpression中,该常量在返回的EnumerableQuery对象中引用。

– Mark Cidade
2012年5月5日18:19



相关问题:IEnumerable 和IQueryable 澄清?

–克里斯托弗·史蒂文森(Christopher Stevenson)
2012年8月14日20:11



值得阅读这篇文章

– JeonD
13-10-30在4:07



@JenonD链接已死,这是Waybackmachine:web.archive.org/web/20160904162931/http://www.dotnet-tricks.com/…

– majjam
18-11-15在12:31

#2 楼

主要区别在于IQueryable<T>的LINQ运算符采用Expression对象而不是委托,这意味着它接收的自定义查询逻辑(例如谓词或值选择器)采用表达式树的形式,而不是方法的委托。 br />

IEnumerable<T>非常适合处理在内存中迭代的序列,但是

IQueryable<T>允许内存不足之类的事情,例如远程数据源数据库或Web服务。

查询执行:


要在“处理中”执行查询的位置,通常所需要做的就是代码(作为代码)执行查询的每个部分。


执行将在进程外执行,则查询的逻辑必须用这样的数据表示: LINQ提供程序可以将其转换为适当的形式以进行内存不足的执行-无论是LDAP查询,SQL还是其他任何方法。 br /> LINQ: IEnumerable<T>IQueryable<T>

C#3.0和LINQ。
“返回IEnumerable<T>IQueryable<T>
2018年:来自Bart De Smet的“年度最有趣的界面……IEnumerable”。



评论


我喜欢提到内存不足的操作。它阐明了实际使用中的实际差异。

–Ishmael Smyrnow
2011年6月30日在16:29

IQueryable 将采用Expression 参数,而不是像IEnumerable where方法那样将委托作为参数。我们没有将代码传递给IQueryable ,而是将表达式树(作为数据的代码)传递给LINQ提供程序进行分析。 C#3.0和LINQ

–Lu55
2012年5月18日14:13



图片链接出现问题,由于某种原因其未在帖子正文中呈现codeproject.com/KB/cs/646361/WhatHowWhere.jpg

– jbooker
18年8月8日,0:45

@joey但是,我在此答案中看到的图像很好:i.stack.imgur.com/2DAqv.jpg

–VonC
18年8月8日在4:31

这个答案是好的,直到表示并发,拉与推的嘈杂图,IObservable ,其中只有约5%的图与IEnumerable 和IQueryable 有关。这同样适用于“响应式编程”的链接,其中IEnumerable / IQueryable 之间的区别仅用作响应式扩展的介绍。另外,我建议您提供指向本年度最有趣的界面的链接... Bart de Smet的IQueryable

– Zev Spitz
9月3日,22:24

#3 楼

这是youtube上的精彩视频,展示了这些界面的不同之处,值得一看。

下面是一个很长的描述性答案。

要记住的第一个重要点是IQueryable接口继承自IEnumerable,因此无论IEnumerable可以做什么,IQueryable都可以做。 br />


有很多区别,但让我们讨论一个最大的区别。当使用IEnumerable或Entity Framework加载集合时,并且要在集合上应用过滤器时,LINQ接口非常有用。请考虑以下简单代码,它将IEnumerable与实体框架一起使用。它使用Where过滤器来获取EmpId2的记录。

EmpEntities ent = new EmpEntities();
IEnumerable<Employee> emp = ent.Employees; 
IEnumerable<Employee> temp = emp.Where(x => x.Empid == 2).ToList<Employee>();


该过滤器在IEnumerable代码所在的客户端执行。换句话说,所有数据都是从数据库中获取的,然后在客户端进行扫描并通过EmpId获得的记录是2。我们将IEnumerable更改为IQueryable。它在服务器端创建一个SQL查询,并且仅将必要的数据发送到客户端。

EmpEntities ent = new EmpEntities();
IQueryable<Employee> emp = ent.Employees;
IQueryable<Employee> temp =  emp.Where(x => x.Empid == 2).ToList<Employee>();




IQueryableIEnumerable关于执行过滤器逻辑的位置。一个在客户端执行,另一个在数据库执行。

因此,如果仅使用内存数据收集,则IEnumerable是一个不错的选择,但是如果要查询与之关联的数据收集IQueryable数据库是一个更好的选择,因为它减少了网络流量并使用了SQL语言的功能。

评论


嗨,非常感谢您的精彩解释。我知道为什么IQueryable是“内存不足”数据的更好选择,但我仍在努力理解IEnumerable为什么“内存不足”的数据更好?我仍然认为获取过滤的数据比获取数据并应用过滤器要好。

– Imad
19年3月1日在4:35

当它是“内存中”时,这并不重要。数据已经在内存中了,过滤的确切时间无关紧要。

–罗尼·阿克塞拉德(Roni Axelrad)
19年6月13日在15:43

@Imad例如,使用IQueryable或EntityFunctions不可能通过将实体DateTimeOffset转换为DateTime来投影数据。最好的方法是先将AsEnumerable()实体对象,然后将Select()放入包含DateTime的视图模型中。此过程使用内存中功能。

–杰夫
19年11月2日,3:13



#4 楼

IEnumerable:
IEnumerable最适合用于内存中的集合(或本地查询)。
IEnumerable不会在项目之间移动,它是仅转发集合。 :
IQueryable最适合于远程数据源,例如数据库或Web服务(或远程查询)。查询)。

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

评论


IEnumerable不会使用延迟执行吗?

–伊恩·沃伯顿(Ian Warburton)
13年6月29日在18:14

IEnumerable和IQueryable中都提供了延迟执行。更多有趣的信息可以在这里找到:stackoverflow.com/questions/2876616/…

–伊格纳西奥(Ignacio Hagopian)
2014年3月30日在1:34



#5 楼

简而言之,另一个主要区别是IEnumerable在服务器端执行select查询,在客户端加载内存中的数据,然后过滤数据,而IQueryable在服务器端使用所有过滤器执行select查询。

#6 楼

在现实生活中,如果您使用的是像LINQ-to-SQL这样的ORM,则可以将查询转换为sql并在数据库服务器上运行。 />如果创建IEnumerable,则在运行查询之前,所有行都将作为对象拉入内存。使用它的时间,例如,您有一个ToList()并从中填充了4个列表框,那么该查询将针对数据库运行4次。 br />
q.Where(x.name = "a").ToList()


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

#7 楼

以下提到的小测试可能会帮助您了解IQueryable<T>IEnumerable<T>之间的差异的一方面。我从这篇文章中重现了这个答案,我试图在其他人的文章中添加更正内容

我在DB(DDL脚本)中创建了以下结构: />
这是记录插入脚本(DML脚本): 。我将ADO.NET实体数据模型项添加到指向数据库中Employee表的控制台应用程序中,并开始编写LINQ查询。

可查询路线的代码:

CREATE TABLE [dbo].[Employee]([PersonId] [int] NOT NULL PRIMARY KEY,[Salary] [int] NOT NULL)


当我开始运行该程序时,我还已经在SQL Server实例上启动了SQL Query Profiler的会话,这是执行摘要:


发出的查询总数:1
查询文本:Employee


SELECT TOP (2) [c].[Salary] AS [Salary] FROM [dbo].[Employee] AS [c]足够聪明,可以将IQueryable子句应用于数据库服务器端本身,因此仅带来2个超过5条记录。客户端计算机端根本不需要任何进一步的内存过滤。

IEnumerable路由的代码:这种情况:


已发出的查询总数:1
在SQL事件探查器中捕获的查询文本:Top (2)


现在问题是SELECT [Extent1].[Salary] AS [Salary] FROM [dbo].[Employee] AS [Extent1]带来了IEnumerable表中存在的所有5条记录,然后在客户端计算机上执行了内存中筛选以获取前2条记录。因此,不必要地通过导线传输了更多数据(在这种情况下,增加了3条记录)。

#8 楼

IEnumerable引用了一个集合,但是IQueryable只是一个查询,它将在一个Expression Tree中生成。我们将运行此查询从数据库中获取数据。

#9 楼

这是我在类似帖子(关于此主题)上写的内容。 (并且不,我通常不引述自己,但是这些都是非常好的文章。) />
引用该文章,“根据MSDN文档,对IQueryable的调用通过构建内部表达式树来进行。
”这些扩展IQueryable(Of T)的方法不会执行任何查询直。相反,它们的功能是构建一个Expression对象,这是一个表示累积查询的表达式树。 “'

表达树是C#和.NET平台上非常重要的结构。(它们通常很重要,但是C#使它们非常有用。)为了更好地理解它们之间的差异,建议阅读关于官方C#5.0规范中表达式和语句之间的区别的信息。对于分支到lambda微积分的高级理论概念,表达式使对方法的支持成为一等对象。表达式树,而IEnumerable则不行,至少对于那些不在Microsoft秘密实验室工作的人来说,至少不是一般而言。 vs. pull透视图。(通过“ push”与“ pull”,我指的是数据流的方向。.NET和C#的反应式编程技术在这里是一篇非常好的文章,详细介绍lambd语句之间的差异as和expression lambdas并更深入地讨论了expression tress的概念:重新讨论C#委托,表达式树和lambda语句与lambda表达式。.“

#10 楼

我们使用IEnumerableIQueryable来处理从数据库检索的数据。 IQueryable继承自IEnumerable,因此IQueryable确实包含所有IEnumerable功能。 IQueryableIEnumerable之间的主要区别在于,IQueryable使用过滤器执行查询,而IEnumerable首先执行查询,然后根据条件过滤数据。

在下面找到更详细的区别:

IEnumerable



IEnumerable存在于System.Collections名称空间中

IEnumerable在服务器端执行选择查询,将数据加载到内存中客户端,然后过滤数据

IEnumerable适用于从列表,数组之类的内存集合中查询数据。

可查询的




IEnumerable存在于IQueryable名称空间中

System.Linq在服务器端执行“选择查询”具有所有过滤器的

IQueryable适用于从内存(如远程数据库,服务)集合中查询数据

IQueryable对于LINQ to SQL查询来说很有益
因此,IQueryable通常用于处理内存中的集合,而IEnumerable通常用于处理集合。

#11 楼

如果我们要处理来自数据库的大量数据,则IQueryable比IEnumerable更快,因为IQueryable仅从数据库中获取必需的数据,而IEnumerable则从数据库中获取所有数据,而不必从数据库中获取任何数据

#12 楼

ienumerable:当我们要处理进程内存时,即没有数据连接
iqueryable:当要处理sql server,即数据连接时