IQueryable<T>和IEnumerable<T>之间的区别是什么?
另见IQueryable和IEnumerable之间的区别是什么,与这个问题重叠。
IQueryable<T>和IEnumerable<T>之间的区别是什么?
另见IQueryable和IEnumerable之间的区别是什么,与这个问题重叠。
当前回答
下面提到的小测试可能会帮助你理解IQueryable<T>和IEnumerable<T>之间的一个区别。我从这篇文章中复制了这个答案,我试图对其他人的帖子进行更正
我在DB (DDL脚本)中创建了以下结构:
CREATE TABLE [dbo].[Employee]([PersonId] [int] NOT NULL PRIMARY KEY,[Salary] [int] NOT NULL)
下面是记录插入脚本(DML脚本):
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(1, 20)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(2, 30)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(3, 40)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(4, 50)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(5, 60)
GO
现在我的目标是从数据库中的Employee表中获得前2条记录。在Visual Studio (VS)中创建了一个新的c#控制台应用程序。然后,我添加了一个ADO。NET实体数据模型XML (EDMX)项指向数据库中的Employee表。现在我可以开始编写LINQ查询了。
案例一:IQueryable路由代码
using (var efContext = new EfTestEntities())
{
IQueryable<int> employees = from e in efContext.Employees select e.Salary;
employees = employees.Take(2);
foreach (var item in employees)
{
Console.WriteLine(item);
}
}
在运行这个程序之前,我已经在SQL Server实例上启动了一个SQL查询分析器会话。以下是执行概要:
触发的查询总数:1 查询文本: SELECT TOP (2) [c]。[薪金]AS[薪金]来自[dbo]。[雇员]AS [c]
我们可以看到IQueryable足够聪明,可以在数据库服务器端本身应用Top(2)子句。所以它只通过网络带来5条记录中的2条。在客户端不需要更多的内存过滤。
案例二:IEnumerable路由的代码
using (var efContext = new EfTestEntities())
{
IEnumerable<int> employees = from e in efContext.Employees select e.Salary;
employees = employees.Take(2);
foreach (var item in employees)
{
Console.WriteLine(item);
}
}
本例执行摘要:
触发的查询总数:1 SQL分析器捕获的查询文本: 选择[Extent1]。[薪金]AS[薪金]来自[dbo]。[雇员]AS [Extent1]
现在需要注意的是,IEnumerable带来了Salary表中的所有5条记录,然后在客户端执行内存过滤以获得前2条记录。因此更多的数据(在本例中是3条额外的记录)通过网络传输,不必要地消耗了带宽。
其他回答
主要的区别是IQueryable<T>的LINQ操作符接受表达式对象而不是委托,这意味着它接收的自定义查询逻辑,例如,谓词或值选择器,是表达式树的形式,而不是方法的委托。
IEnumerable<T>非常适合处理在内存中迭代的序列,但是 IQueryable<T>允许内存不足的事情,如远程数据源,如数据库或web服务。
查询执行:
查询的执行将在“进程中”执行,通常所需要的只是执行查询的每个部分的代码(作为代码)。 在将在进程外执行的地方,查询的逻辑必须用数据表示,以便LINQ提供程序可以将其转换为内存外执行的适当形式——无论是LDAP查询、SQL查询还是其他查询。
更多:
LINQ: IEnumerable<T> and IQueryable<T> c# 3.0和LINQ。 返回IEnumerable<T> vs IQueryable<T> 面向。net和c#开发人员的响应式编程——IEnumerable, IQueryable, IObservable和iqobservable的介绍 2008年:巴特·德·斯梅特的“年度最有趣的界面…可查询<T>”。
我们使用IEnumerable和IQueryable来操作从数据库中检索的数据。IQueryable继承自IEnumerable,所以IQueryable包含了IEnumerable的所有特性。IQueryable和IEnumerable之间的主要区别是IQueryable使用过滤器执行查询,而IEnumerable先执行查询,然后根据条件过滤数据。
更详细的区别如下:
IEnumerable
IEnumerable在系统中存在。集合名称空间 IEnumerable在服务器端执行选择查询,在客户端加载内存中的数据,然后筛选数据 IEnumerable适用于从List、Array等内存集合中查询数据 IEnumerable有利于LINQ to Object和LINQ to XML查询
这个IQueryable
系统中存在IQueryable功能。Linq命名空间 IQueryable在服务器端执行一个带有所有过滤器的“选择查询” IQueryable适用于从内存外(如远程数据库,服务)集合中查询数据 IQueryable有利于LINQ到SQL的查询
所以IEnumerable通常用于处理内存中的集合,而IQueryable通常用于操作集合。
IEnumerable引用了一个集合,而IQueryable只是一个查询,它将在表达式树中生成。我们将运行这个查询从数据库中获取数据。
在现实生活中,如果您正在使用LINQ-to-SQL之类的ORM
如果您创建了IQueryable查询,那么该查询可能会转换为sql并在数据库服务器上运行 如果您创建了一个IEnumerable,那么在运行查询之前,所有行都将作为对象拉入内存。
在这两种情况下,如果你不调用ToList()或ToArray(),那么查询将在每次使用它时执行,所以,比如说,你有一个IQueryable<T>,你从它填充4个列表框,那么查询将对数据库运行4次。
同样,如果你扩展你的查询:
q.Where(x.name = "a").ToList()
然后使用IQueryable生成的SQL将包含" where name = " a ",但是使用IEnumerable会从数据库中拉回更多的角色,然后. net将完成x.name = " a "检查。
以下是我在类似的帖子(关于这个话题)上所写的内容。(不,我通常不引用自己的话,但这些都是非常好的文章。)
这篇文章很有帮助: LINQ-to-SQL中的IQueryable和IEnumerable。
引用那篇文章,“根据MSDN文档,对IQueryable调用通过构建内部表达式树来操作。 这些扩展IQueryable(Of T)的方法不直接执行任何查询。相反,它们的功能是构建Expression对象,该对象是表示累积查询的表达式树。“‘
Expression trees are a very important construct in C# and on the .NET platform. (They are important in general, but C# makes them very useful.) To better understand the difference, I recommend reading about the differences between expressions and statements in the official C# 5.0 specification here. For advanced theoretical concepts that branch into lambda calculus, expressions enable support for methods as first-class objects. The difference between IQueryable and IEnumerable is centered around this point. IQueryable builds expression trees whereas IEnumerable does not, at least not in general terms for those of us who don't work in the secret labs of Microsoft.
下面是另一篇非常有用的文章,从推和拉的角度详细介绍了两者的区别。(通过“push”和“。“拉”,我指的是数据流的方向。用于。net和c#的响应式编程技术
这是一篇非常好的文章,详细介绍了语句lambdas和表达式lambdas之间的区别,并更深入地讨论了表达式树的概念:重访c#委托、表达式树和lambda语句与lambda表达式。”