首页 文章

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

提问于
浏览
386

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


另见What's the difference between IQueryable and IEnumerable与此问题重叠 .

12 回答

  • 181

    首先,IQueryable<T>扩展了 IEnumerable<T> 接口,所以你可以用"plain" IEnumerable<T> 做任何事情,你也可以用 IQueryable<T> 做 .

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

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

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

  • 51

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

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

    • IQueryable<T> 允许远程数据源(如数据库或Web服务)之类的内存不足 .

    查询执行:

    • 如果要执行查询的执行 "in process" ,通常所需要的只是执行查询的每个部分的代码(作为代码) .

    • 执行将执行 out-of-process ,查询的逻辑必须在数据中表示,以便LINQ提供程序可以将其转换为适当的形式以进行内存不足执行 - 无论是LDAP查询,SQL还是其他 .

    更多内容:

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

  • 9

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

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

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

    enter image description here

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

    考虑下面使用 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语言的强大功能 .

  • 6

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

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

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

  • 16

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

  • 236

    在现实生活中,如果您使用的是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完成 .

  • 7

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

  • 0

    下面提到的小测试可能会帮助您理解 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查询 .

    Code for IQueryable route

    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

    • 查询文字: SELECT TOP (2) [c].[Salary] AS [Salary] FROM [dbo].[Employee] AS [c]

    只是 IQueryable 足够聪明,可以在数据库服务器端本身应用 Top (2) 子句,因此它只能通过网络传输5条记录中的2条 . 客户端计算机端根本不需要任何进一步的内存中过滤 .

    Code for IEnumerable route

    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事件探查器中捕获的查询文本: SELECT [Extent1].[Salary] AS [Salary] FROM [dbo].[Employee] AS [Extent1]

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

  • -1

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

    “这篇文章很有帮助: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则没有,至少对于我们这些不在微软秘密实验室工作的人来说,这一点并非一般 .

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

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

  • 0

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

  • 17

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

  • 161

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

相关问题