IQueryable <T>和IEnumerable <T>有什么区别?

410 .net linq ienumerable iqueryable .net-3.5

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


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

Mar*_*ade 250

首先,扩展的接口,所以任何你可以用一个"普通"做,你也可以做用.IQueryable<T> IEnumerable<T>IEnumerable<T>IQueryable<T>

IEnumerable<T>只是有一个GetEnumerator()返回的方法Enumerator<T>,而您可以调用它的MoveNext()方法通过序列迭代牛逼.

什么IQueryable<T>具有IEnumerable<T> 是特别-一个指向一个两个属性查询提供(例如,LINQ到SQL提供商)和另一个指向一个查询表达式表示所述IQueryable<T>对象作为运行时间横越抽象语法树,可以是由给定的查询提供程序理解(在大多数情况下,您不能在没有抛出异常的情况下将LINQ to SQL表达式提供给LINQ to Entities提供程序).

表达式可以简单地是对象本身的常量表达式,也可以是组合的查询运算符和操作数集的更复杂的树.通过传递给它的Expression调用查询提供程序IQueryProvider.Execute()IQueryProvider.CreateQuery()方法,然后分别返回查询结果或其他结果.IQueryable

  • 使用AsQueryable有什么好处吗? (8认同)
  • 唯一的好处是方便.`AsQueryable()`只会将一个枚举强制转换为可查询并返回它,如果它实现了`IQueryable`接口,否则它将它包装在`ConstantExpression`中,它在返回的`EnumerableQuery`对象中引用. (6认同)
  • 相关问题:[IEnumerable <T>和IQueryable <T>澄清?](http://stackoverflow.com/questions/11132888/ienumerablet-and-iqueryablet-clarification?lq=1) (3认同)
  • 值得一读[文章](http://www.dotnet-tricks.com/Tutorial/linq/I8SY160612-IEnumerable-VS-IQueryable.html) (2认同)
  • @JenonD 链接已死,这里是waybackmachine:https://web.archive.org/web/20160904162931/http://www.dotnet-tricks.com/Tutorial/linq/I8SY160612-IEnumerable-VS-IQueryable.html (2认同)

Von*_*onC 195

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

  • IEnumerable<T> 非常适合处理在内存中迭代的序列,但是
  • IQueryable<T> 允许内存不足的东西,如远程数据源,如数据库或Web服务.

查询执行:

  • "正在处理"中执行查询的情况下,通常所需要的只是执行查询的每个部分的代码(作为代码).

  • 如果执行将在进程外执行,则查询的逻辑必须在数据中表示,以便LINQ提供程序可以将其转换为适合于内存不足执行的形式 - 无论这是否是LDAP查询, SQL或其他什么.

更多内容:

http://www.codeproject.com/KB/cs/646361/WhatHowWhere.jpg

  • 我喜欢提到内存不足的操作.它澄清了使用中真正的实际差异. (14认同)
  • 而不是将代理作为IEnumerable <T> Where方法所做的参数,IQueryable <T>将采用Expression <TDelegate>参数.我们没有将代码传递给IQueryable <T>,我们正在传递表达式树(代码作为数据)供LINQ提供程序进行分析.[C#3.0和LINQ](http://odetocode.com/Articles/738.aspx) (2认同)

Shi*_*ala 179

这是一个关于youtube的精彩视频,展示了这些界面的不同之处,值得一看.

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

要记住的第一个要点是IQueryable接口继承IEnumerable,所以无论IEnumerable做什么,IQueryable也可以做.

在此输入图像描述

有许多不同之处,但让我们讨论一下产生最大差异的一大差异.IEnumerable使用LINQ或Entity框架加载集合时,接口非常有用,并且您希望对集合应用过滤器.

考虑下面IEnumerable与实体框架一起使用的简单代码.它使用一个Where过滤器来获得其记录EmpId2.

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

这是在IEnumerable代码所在的客户端执行过滤器的地方.换句话说,所有数据都是从数据库中获取的,然后在客户端进行扫描,并使用EmpIdis 获取记录2.

在此输入图像描述

但现在看下面的代码,我们已经改变IEnumerableIQueryable.它在服务器端创建一个SQL查询,只将必要的数据发送到客户端.

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

在此输入图像描述

因此,IQueryable和之间的区别在于IEnumerable执行过滤器逻辑的位置.一个在客户端执行,另一个在数据库上执行.

因此,如果您只使用内存中的数据收集IEnumerable是一个不错的选择,但如果您想查询与数据库连接的数据集合,那么IQueryable是一个更好的选择,因为它可以减少网络流量并使用SQL语言的强大功能.


Tal*_*lha 55

IEnumerable: IEnumerable最适合处理内存中的集合(或本地查询).IEnumerable不会在项目之间移动,它只是前向收集.

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

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

  • IEnumerable不使用延迟执行吗? (3认同)
  • IEnumerable和IQueryable都提供了延迟执行.更多有趣的信息可以在这里找到:http://stackoverflow.com/questions/2876616/returning-ienumerablet-vs-iqueryablet (3认同)

A.T*_*.T. 18

简单来说,其他主要区别在于IEnumerable在服务器端执行select查询,在客户端加载数据在内存中,然后在IQueryable上使用所有过滤器在服务器端执行select查询时过滤数据.


Ian*_*ose 17

在现实生活中,如果您使用的是LINQ-to-SQL之类的ORM

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

在这两种情况下,如果你不调用a ToList(),ToArray()那么每次使用时都会执行查询,所以,比方说,你有一个IQueryable<T>并从中填充4个列表框,然后查询将对数据库运行4次.

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

q.Where(x.name = "a").ToList()
Run Code Online (Sandbox Code Playgroud)

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


小智 10

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


RBT*_*RBT 8

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

我在DB(DDL脚本)中创建了以下结构:

CREATE TABLE [dbo].[Employee]([PersonId] [int] NOT NULL PRIMARY KEY,[Salary] [int] NOT NULL)
Run Code Online (Sandbox Code Playgroud)

这是记录插入脚本(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
Run Code Online (Sandbox Code Playgroud)

现在,我的目标是简单地从Employee数据库中的表中获取前2条记录.我在我的控制台应用程序中添加了一个ADO.NET实体数据模型项,指向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);
    }
}
Run Code Online (Sandbox Code Playgroud)

当我开始运行这个程序时,我还在我的SQL Server实例上启动了一个SQL Query profiler会话,这里是执行摘要:

  1. 触发的查询总数:1
  2. 查询文字: SELECT TOP (2) [c].[Salary] AS [Salary] FROM [dbo].[Employee] 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下执行摘要:

  1. 触发的查询总数:1
  2. 在SQL事件探查器中捕获的查询文本: SELECT [Extent1].[Salary] AS [Salary] FROM [dbo].[Employee] AS [Extent1]

现在,事物将IEnumerable带来Salary表中存在的所有5条记录,然后在客户端计算机上执行内存中过滤以获得前2条记录.因此,不必要地通过线路传输更多数据(在这种情况下为3个附加记录).


dev*_*ost 7

这是我在类似帖子上写的(关于这个主题).(不,我通常不引用自己,但这些都是非常好的文章.)

"本文很有帮助: 在LINQ-to-SQL中,IQueryable vs IEnumerable.

引用该文章,"根据MSDN文档,对IQueryable进行的调用通过构建内部表达式树来进行操作."这些扩展IQueryable(Of T)的方法不会直接执行任何查询.相反,它们的功能是构建一个Expression对象,它是一个表示累积查询的表达式树."

表达式树是C#和.NET平台上非常重要的构造.(它们通常很重要,但C#使它们非常有用.)为了更好地理解差异,我建议在这里阅读官方C#5.0规范中表达式语句 之间的差异.对于分支为lambda演算的高级理论概念,表达式支持将方法作为第一类对象.IQueryable和IEnumerable之间的区别在于这一点.IQueryable构建了表达式树,而IEnumerable则没有,至少对于我们这些不在微软秘密实验室工作的人来说,这一点并非一般.

这是另一篇非常有用的文章,详细介绍了推送与拉动视角的差异.(通过"推"与"拉",我指的是数据流的方向.针对.NET和C#的反应式编程技术

这是一篇非常好的文章,详细介绍了语句lambdas和表达式lambdas之间的区别,并更深入地讨论了表达式tress的概念:重温C#委托,表达式树和lambda语句与lambda表达式.".


Vik*_*ore 7

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

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

IEnumerable

  1. IEnumerable存在于System.Collections命名空间中
  2. IEnumerable 在服务器端执行选择查询,在客户端加载内存中的数据,然后过滤数据
  3. IEnumerable 适用于从内存集合(如 List、Array)中查询数据
  4. IEnumerable 有利于 LINQ to Object 和 LINQ to XML 查询

可查询

  1. IQueryable存在于System.Linq命名空间中
  2. IQueryable 使用所有过滤器在服务器端执行“选择查询”
  3. IQueryable 适用于从内存外(如远程数据库、服务)集合中查询数据
  4. IQueryable 有利于 LINQ to SQL 查询

soIEnumerable一般用于处理内存中的集合,而,IQueryable一般用于操作集合。