IQueryable <t>和IEnumerable <t>之间有什么区别?</t> </t>

时间:2008-10-31 07:18:43

标签: .net linq .net-3.5 ienumerable iqueryable

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


另请参阅与此问题重叠的What's the difference between IQueryable and IEnumerable

13 个答案:

答案 0 :(得分:246)

首先,IQueryable<T> 扩展 IEnumerable<T>界面,所以你可以用“普通”IEnumerable<T>做任何事情,你也可以用IQueryable<T>

IEnumerable<T>只有GetEnumerator()方法返回Enumerator<T>,您可以调用其MoveNext()方法来迭代 T

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

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

答案 1 :(得分:188)

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

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

查询执行:

  • 如果要执行查询“正在进行中”,通常所需要的只是执行查询的每个部分的代码(作为代码)。

  • 如果执行进程外,则必须在数据中表示查询的逻辑,以便LINQ提供程序可以将其转换为适当的形式内存不足执行 - 无论是LDAP查询,SQL还是其他任何内容。

更多信息:

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

答案 2 :(得分:172)

这是一个很好的video on youtube,它展示了这些界面的不同之处,值得一看。

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

要记住的第一个要点是IQueryable接口继承自IEnumerable,因此无论IEnumerable能做什么,IQueryable也可以做。

enter image description here

有许多不同之处,但让我们讨论一下产生最大差异的一大差异。使用IEnumerable或实体框架加载集合并且您希望对集合应用过滤器时, 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

enter image description here

但现在看到以下代码我们已将 IEnumerable 更改为 IQueryable 。它在服务器端创建一个SQL查询,只将必要的数据发送到客户端。

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

enter image description here

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

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

答案 3 :(得分:54)

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

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

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

答案 4 :(得分:18)

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

答案 5 :(得分:17)

在现实生活中,如果你正在使用像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,将从数据库中撤回更多的角色,然后x.name =”a“检查将完成。 NET。

答案 6 :(得分:10)

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

答案 7 :(得分:8)

下面提到的小测试可能有助于您了解IQueryable<T>IEnumerable<T>之间差异的一个方面。我已经从this帖子中复制了这个答案,我试图在其他人的帖子中添加更正

我在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条记录。我在我的控制台应用程序中添加了一个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);
    }
}

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

  1. 触发的查询总数:1
  2. 查询文字:SELECT TOP (2) [c].[Salary] AS [Salary] FROM [dbo].[Employee] AS [c]
  3. 只是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. 触发的查询总数:1
    2. 查询在SQL事件探查器中捕获的文本:SELECT [Extent1].[Salary] AS [Salary] FROM [dbo].[Employee] AS [Extent1]
    3. 现在问题IEnumerable带来了Salary表中存在的所有5条记录,然后在客户端计算机上执行了内存过滤以获得前2条记录。因此,更多的数据(在这种情况下为3个额外的记录)不必要地通过线路传输。

答案 8 :(得分:7)

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

“这篇文章很有帮助: IQueryable vs IEnumerable in LINQ-to-SQL

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

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

这是另一篇非常有用的文章,详细介绍了推送与拉动视角的差异。 (通过“推”与“拉”,我指的是数据流的方向。Reactive Programming Techniques for .NET and C#

这是一篇非常好的文章,详细介绍了语句lambdas和表达式lambdas之间的区别,并更深入地讨论了表达式tress的概念:Revisiting C# delegates, expression trees, and lambda statements vs. lambda expressions.。“

答案 9 :(得分:2)

IEnumerable和IQueryable都用于保存数据集合并执行数据操作操作,例如过滤数据集合。 在这里,您可以找到与示例的最佳差异比较。 http://www.gurujipoint.com/2017/05/difference-between-ienumerable-and.html enter image description here

答案 10 :(得分:2)

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

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

IEnumerable

  1. IEnumerable存在于System.Collections名称空间中
  2. IEnumerable在服务器端执行选择查询,在客户端将数据加载到内存中,然后过滤数据
  3. IEnumerable适用于查询列表,数组之类的内存中的数据
  4. IEnumerable对于LINQ to Object和LINQ to XML查询都是有益的

可查询

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

因此IEnumerable通常用于处理内存中的集合,而IQueryable通常用于处理集合。

答案 11 :(得分:1)

如果我们处理来自数据库的大量数据,IQueryable比IEnumerable更快,因为IQueryable只从数据库中获取所需数据,而IEnumerable从数据库获取所有数据,无论数据库是否必要

答案 12 :(得分:0)

ienumerable:当我们想处理进程内存时,即没有dataconnection iqueryable:何时处理sql server,即与数据连接 ilist:添加对象,删除对象等操作