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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/252785/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 10:28:51  来源:igfitidea点击:

What is the difference between IQueryable<T> and IEnumerable<T>?

.netlinq.net-3.5ienumerableiqueryable

提问by

What is the difference between IQueryable<T>and IEnumerable<T>?

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



See also What's the difference between IQueryable and IEnumerablethat overlaps with this question.

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

回答by Mark Cidade

First of all, IQueryable<T>extendsthe IEnumerable<T>interface, so anything you can do with a "plain" IEnumerable<T>, you can also do with an IQueryable<T>.

首先,扩展的接口,因此任何你可以做一个“普通” ,你也可以用做。IQueryable<T>IEnumerable<T>IEnumerable<T>IQueryable<T>

IEnumerable<T>just has a GetEnumerator()method that returns an Enumerator<T>for which you can call its MoveNext()method to iterate through a sequence of T.

IEnumerable<T>只是有一个GetEnumerator()返回a 的方法,Enumerator<T>您可以调用其MoveNext()方法来遍历T序列。

What IQueryable<T>has that IEnumerable<T>doesn'tare two properties in particular—one that points to a query provider(e.g., a LINQ to SQL provider) and another one pointing to a query expressionrepresenting the IQueryable<T>object as a runtime-traversable abstract syntax tree that can be understood by the given query provider (for the most part, you can't give a LINQ to SQL expression to a LINQ to Entities provider without an exception being thrown).

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

The expression can simply be a constant expression of the object itself or a more complex tree of a composed set of query operators and operands. The query provider's IQueryProvider.Execute()or IQueryProvider.CreateQuery()methods are called with an Expressionpassed to it, and then either a query result or another IQueryableis returned, respectively.

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

回答by VonC

The primary difference is that the LINQ operators for IQueryable<T>take Expressionobjects instead of delegates, meaning the custom query logic it receives, e.g., a predicate or value selector, is in the form of an expression tree instead of a delegate to a method.

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

  • IEnumerable<T>is great for working with sequences that are iterated in-memory, but
  • IQueryable<T>allows for out-of memory things like a remote data source, such as a database or web service.
  • IEnumerable<T>非常适合处理在内存中迭代的序列,但是
  • IQueryable<T>允许内存不足的情况,例如远程数据源,例如数据库或 Web 服务。

Query execution:

查询执行:

  • Where the execution of a query is going to be performed "in process", typically all that's required is the code (as code) to execute each part of the query.

  • Where the execution will be performed out-of-process, the logic of the query has to be represented in data such that the LINQ provider can convert it into the appropriate form for the out-of-memory execution - whether that's an LDAP query, SQL or whatever.

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

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

More in:

更多内容:

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

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

回答by Shivprasad Ktheitroadala

This is a nice video on youtubewhich demonstrates how these interfaces differ , worth a watch.

这是YouTube 上的一个不错的视频,演示了这些界面的不同之处,值得一看。

Below goes a long descriptive answer for it.

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

The first important point to remember is IQueryableinterface inherits from IEnumerable, so whatever IEnumerablecan do, IQueryablecan also do.

要记住的第一个重点是IQueryable接口继承自IEnumerable,所以IEnumerable能做的,IQueryable也能做。

enter image description here

在此处输入图片说明

There are many differences but let us discuss about the one big difference which makes the biggest difference. IEnumerableinterface is useful when your collection is loaded using LINQor Entity framework and you want to apply filter on the collection.

有很多不同之处,但让我们讨论最大的不同之处。IEnumerable当您的集合使用LINQ或 实体框架加载并且您想对集合应用过滤器时,接口很有用。

Consider the below simple code which uses IEnumerablewith entity framework. It's using a Wherefilter to get records whose EmpIdis 2.

考虑以下IEnumerable与实体框架一起使用的简单代码。它使用Where过滤器来获取其EmpId为 的记录2

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

This where filter is executed on the client side where the IEnumerablecode is. In other words all the data is fetched from the database and then at the client its scans and gets the record with EmpIdis 2.

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

enter image description here

在此处输入图片说明

But now see the below code we have changed IEnumerableto IQueryable. It creates a SQL Query at the server side and only necessary data is sent to the client side.

但是现在请看下面的代码,我们已更改IEnumerableIQueryable. 它在服务器端创建一个 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

在此处输入图片说明

So the difference between IQueryableand IEnumerableis about where the filter logic is executed. One executes on the client side and the other executes on the database.

所以之间的差IQueryableIEnumerable大约为执行过滤器逻辑位置。一个在客户端执行,另一个在数据库上执行。

So if you working with only in-memory data collection IEnumerableis a good choice but if you want to query data collection which is connected with database `IQueryable is a better choice as it reduces network traffic and uses the power of SQL language.

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

回答by Talha

IEnumerable:IEnumerable is best suitable for working with in-memory collection (or local queries). IEnumerable doesn't move between items, it is forward only collection.

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

IQueryable:IQueryable best suits for remote data source, like a database or web service (or remote queries). IQueryable is a very powerful feature that enables a variety of interesting deferred execution scenarios (like paging and composition based queries).

IQueryable:IQueryable 最适合远程数据源,如数据库或 Web 服务(或远程查询)。IQueryable 是一个非常强大的功能,它支持各种有趣的延迟执行场景(如基于分页和组合的查询)。

So when you have to simply iterate through the in-memory collection, use IEnumerable, if you need to do any manipulation with the collection like Dataset and other data sources, use IQueryable

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

回答by A.T.

In simple words other major difference is that IEnumerable execute select query on server side, load data in-memory on client side and then filter data while IQueryable execute select query on server side with all filters.

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

回答by Ian Ringrose

In real life, if you are using a ORM like LINQ-to-SQL

在现实生活中,如果您使用的是像 LINQ-to-SQL 这样的 ORM

  • If you create an IQueryable, then the query may be converted to sql and run on the database server
  • If you create an IEnumerable, then all rows will be pulled into memory as objects before running the query.
  • 如果你创建了一个 IQueryable,那么查询可能会被转换成 sql 并在数据库服务器上运行
  • 如果您创建一个 IEnumerable,那么在运行查询之前,所有行都将作为对象被拉入内存。

In both cases if you don't call a ToList()or ToArray()then query will be executed each time it is used, so, say, you have an IQueryable<T>and you fill 4 list boxes from it, then the query will be run against the database 4 times.

在这两种情况下,如果您不调用 a ToList()ToArray()则每次使用时都会执行查询,因此,假设您有一个IQueryable<T>并且您从中填充了 4 个列表框,那么该查询将针对数据库运行 4 次。

Also if you extent your query:

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

q.Where(x.name = "a").ToList()

Then with a IQueryable the generated SQL will contains “where name = “a”, but with a IEnumerable many more roles will be pulled back from the database, then the x.name = “a” check will be done by .NET.

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

回答by seyed

IEnumerable is refering to a collection but IQueryable is just a query and it will be generated inside a Expression Tree.we will run this query to get data from database.

IEnumerable 指的是一个集合,但 IQueryable 只是一个查询,它将在表达式树中生成。我们将运行此查询以从数据库中获取数据。

回答by RBT

Below mentioned small test might help you understand one aspect of difference between IQueryable<T>and IEnumerable<T>. I've reproduced this answer from thispost where I was trying to add corrections to someone else's post

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

I created following structure in DB (DDL script):

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

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

Here is the record insertion script (DML script):

这是记录插入脚本(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

Now, my goal was to simply get top 2 records from Employeetable in database. I added an ADO.NET Entity Data Model item into my console application pointing to Employeetable in my database and started writing LINQ queries.

现在,我的目标是简单地从Employee数据库中的表中获取前 2 条记录。我在控制台应用程序中添加了一个 ADO.NET 实体数据模型项,指向Employee我的数据库中的表并开始编写 LINQ 查询。

Code for IQueryable route:

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);
    }
}

When I started to run this program, I had also started a session of SQL Query profiler on my SQL Server instance and here is the summary of execution:

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

  1. Total number of queries fired: 1
  2. Query text: SELECT TOP (2) [c].[Salary] AS [Salary] FROM [dbo].[Employee] AS [c]
  1. 触发的查询总数:1
  2. 查询文本: SELECT TOP (2) [c].[Salary] AS [Salary] FROM [dbo].[Employee] AS [c]

It is just that IQueryableis smart enough to apply the Top (2)clause on database server side itself so it brings only 2 out of 5 records over the wire. Any further in-memory filtering is not required at all on client computer side.

这仅仅是IQueryable是应用足够聪明,Top (2)所以它带来过线只有2个5个记录数据库服务器端本身的条款。在客户端计算机端根本不需要任何进一步的内存过滤。

Code for IEnumerable route:

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);
    }
}

Summary of execution in this case:

本案执行摘要:

  1. Total number of queries fired: 1
  2. Query text captured in SQL profiler: SELECT [Extent1].[Salary] AS [Salary] FROM [dbo].[Employee] AS [Extent1]
  1. 触发的查询总数:1
  2. 在 SQL 探查器中捕获的查询文本: SELECT [Extent1].[Salary] AS [Salary] FROM [dbo].[Employee] AS [Extent1]

Now the thing is IEnumerablebrought all the 5 records present in Salarytable and then performed an in-memory filtering on the client computer to get top 2 records. So more data (3 additional records in this case) got transferred over the wire unnecessarily.

现在,IEnumerableSalary表中存在的所有 5 条记录带入其中,然后在客户端计算机上执行内存过滤以获取前 2 条记录。因此,不必要地通过网络传输了更多数据(在本例中为 3 个额外记录)。

回答by devinbost

Here is what I wrote on a similar post (on this topic). (And no, I don't usually quote myself, but these are very good articles.)

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

"This article is helpful: IQueryable vs IEnumerable in LINQ-to-SQL.

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

Quoting that article, 'As per the MSDN documentation, calls made on IQueryable operate by building up the internal expression tree instead. "These methods that extend IQueryable(Of T) do not perform any querying directly. Instead, their functionality is to build an Expression object, which is an expression tree that represents the cumulative query. "'

引用那篇文章,“根据 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 expressionsand statementsin 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.

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

Here is another very useful article that details the differences from a push vs. pull perspective. (By "push" vs. "pull," I am referring to direction of data flow. Reactive Programming Techniques for .NET and C#

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

Here is a very good article that details the differences between statement lambdas and expression lambdas and discusses the concepts of expression tress in greater depth: Revisiting C# delegates, expression trees, and lambda statements vs. lambda expressions.."

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

回答by VikrantMore

We use IEnumerableand IQueryableto manipulate the data that is retrieved from database. IQueryableinherits from IEnumerable, so IQueryabledoes contain all the IEnumerablefeatures. The major difference between IQueryableand IEnumerableis that IQueryableexecutes query with filters whereas IEnumerableexecutes the query first and then it filters the data based on conditions.

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

Find more detailed differentiation below :

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

IEnumerable

IEnumerable

  1. IEnumerableexists in the System.Collectionsnamespace
  2. IEnumerableexecute a select query on the server side, load data in-memory on a client-side and then filter data
  3. IEnumerableis suitable for querying data from in-memory collections like List, Array
  4. IEnumerableis beneficial for LINQ to Object and LINQ to XML queries
  1. IEnumerable存在于System.Collections命名空间中
  2. IEnumerable在服务器端执行选择查询,在客户端加载内存中的数据,然后过滤数据
  3. IEnumerable适用于从内存集合(如 List、Array)中查询数据
  4. IEnumerable有利于 LINQ to Object 和 LINQ to XML 查询

IQueryable

可查询

  1. IQueryableexists in the System.Linqnamespace
  2. IQueryableexecutes a 'select query' on server-side with all filters
  3. IQueryableis suitable for querying data from out-memory (like remote database, service) collections
  4. IQueryableis beneficial for LINQ to SQL queries
  1. IQueryable存在于System.Linq命名空间中
  2. IQueryable使用所有过滤器在服务器端执行“选择查询”
  3. IQueryable适用于从内存外(如远程数据库、服务)集合中查询数据
  4. IQueryable有利于 LINQ to SQL 查询

So IEnumerableis generally used for dealing with in-memory collection, whereas, IQueryableis generally used to manipulate collections.

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