Answers:
首先,扩展的接口,因此任何你可以做一个“普通” ,你也可以用做。IQueryable<T>
IEnumerable<T>
IEnumerable<T>
IQueryable<T>
IEnumerable<T>
只是有一个GetEnumerator()
返回的方法,Enumerator<T>
您可以为其调用MoveNext()
方法以迭代T序列。
什么IQueryable<T>
具有IEnumerable<T>
不是特别酮两个属性指向一个查询提供(例如,LINQ到SQL提供商)和另一个指向一个查询表达式表示所述IQueryable<T>
对象作为运行时间横越抽象语法树,可以是给定的查询提供程序可以理解(在大多数情况下,除非抛出异常,否则您不能将LINQ to SQL表达式提供给LINQ to Entities提供程序)。
该表达式可以只是对象本身的常量表达式,也可以是由查询运算符和操作数组成的一组更复杂的树。使用传递给它的表达式调用查询提供程序的IQueryProvider.Execute()
或IQueryProvider.CreateQuery()
方法,然后分别返回查询结果或另一个。IQueryable
AsQueryable()
只会将可枚举类型转换为可查询类型,并在实现IQueryable
接口时将其返回,否则将其包装在ConstantExpression
,该EnumerableQuery
对象在返回的对象中引用 。
主要的区别是,该运营商LINQ为IQueryable<T>
取Expression
对象而不是代表,这意味着它接收自定义查询的逻辑,例如,谓词或值选择器,是一个表达式树,而不是一个委托的方法的形式。
IEnumerable<T>
非常适合处理在内存中迭代的序列,但是 IQueryable<T>
允许内存不足之类的东西,例如远程数据源,例如数据库或Web服务。要在“正在处理中”执行查询的地方,通常所需要做的只是执行查询的每个部分的代码(作为代码)。
如果执行将在进程外执行,则查询的逻辑必须以数据表示,以便LINQ提供程序可以将其转换为适合内存不足执行的形式-无论是LDAP查询, SQL或其他。
更多内容:
这是youtube上的精彩视频,展示了这些界面的不同之处,值得一看。
下面为它提供了一个长的描述性答案。
要记住的第一个重要点是IQueryable
接口继承自IEnumerable
,因此无论IEnumerable
做什么,IQueryable
也可以做到。
差异很多,但让我们讨论一个最大的差异。IEnumerable
当您使用LINQ
或Entity Framework 加载集合时,并且您想在集合上应用过滤器时,界面非常有用。
考虑下面IEnumerable
与实体框架一起使用的简单代码。它使用一个Where
过滤器来获得其记录EmpId
的2
。
EmpEntities ent = new EmpEntities();
IEnumerable<Employee> emp = ent.Employees;
IEnumerable<Employee> temp = emp.Where(x => x.Empid == 2).ToList<Employee>();
该过滤器在IEnumerable
代码所在的客户端执行。换句话说,所有数据都是从数据库中获取的,然后在客户端对其进行扫描并获得EmpId
is 的记录2
。
但是,现在请看下面的代码,我们将其更改IEnumerable
为IQueryable
。它在服务器端创建一个SQL查询,并且仅将必要的数据发送到客户端。
EmpEntities ent = new EmpEntities();
IQueryable<Employee> emp = ent.Employees;
IQueryable<Employee> temp = emp.Where(x => x.Empid == 2).ToList<Employee>();
因此,IQueryable
和之间的区别在于IEnumerable
执行过滤器逻辑的位置。一个在客户端执行,另一个在数据库上执行。
因此,如果仅使用内存数据收集IEnumerable
是一个不错的选择,但是如果要查询与数据库连接的数据收集,则IQueryable是一个更好的选择,因为它减少了网络流量并使用了SQL语言的强大功能。
IEnumerable: IEnumerable最适合用于内存中的收集(或本地查询)。IEnumerable不会在项目之间移动,它是仅转发集合。
IQueryable: IQueryable最适合于远程数据源,例如数据库或Web服务(或远程查询)。IQueryable是一项非常强大的功能,可启用各种有趣的延迟执行方案(如基于分页和基于组合的查询)。
因此,当您只需要简单地遍历内存中的集合时,请使用IEnumerable,如果您需要对集合进行任何操作(如数据集和其他数据源),请使用IQueryable
在现实生活中,如果您使用的是像LINQ-to-SQL这样的ORM
在这两种情况下,如果您不调用a ToList()
,ToArray()
那么每次使用该查询时都会执行一次查询,因此,假设您有一个,IQueryable<T>
并从中填充了4个列表框,则该查询将对数据库运行4次。
另外,如果您扩展查询范围:
q.Where(x.name = "a").ToList()
然后,使用IQueryable生成的SQL将包含“ where name =“ a”,但是使用IEnumerable,将从数据库中拉回更多角色,然后.NET将进行x.name =“ a”检查。
以下提到的小测试可能有助于您了解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条记录。我将ADO.NET实体数据模型项添加到指向Employee
数据库中表的控制台应用程序中,并开始编写LINQ查询。
可查询路线的代码:
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的会话,这是执行摘要:
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);
}
}
在这种情况下的执行摘要:
SELECT [Extent1].[Salary] AS [Salary]
FROM [dbo].[Employee] AS [Extent1]
现在,事物被IEnumerable
带到Salary
表中存在的所有5条记录,然后在客户端计算机上执行内存中筛选以获取前2条记录。因此,多余的数据(在这种情况下为3条附加记录)已通过导线传输。
这是我在类似帖子(关于此主题)上写的内容。(不,我通常不引述自己,但这是非常好的文章。)
“这篇文章很有帮助: LINQ-to-SQL中的IQueryable与IEnumerable。
引用该文章,“根据MSDN文档,对IQueryable的调用是通过构建内部表达式树来进行的。“这些扩展IQueryable(Of T)的方法不会直接执行任何查询。相反,它们的功能是构建一个Expression对象,该对象是表示累积查询的表达式树。”
在C#和.NET平台上,表达式树是非常重要的构造。(它们通常很重要,但是C#使它们非常有用。)为了更好地理解它们之间的区别,建议您在此处阅读正式C#5.0规范中表达式和语句 之间的区别。对于分支到lambda演算的高级理论概念,表达式使支持将方法作为一等对象。IQueryable和IEnumerable之间的差异围绕这一点。IQueryable可以构建表达式树,而IEnumerable则不能,至少对于那些不在Microsoft秘密实验室工作的人来说,至少不是一般而言。
这是另一篇非常有用的文章,从推与拉的角度详细介绍了差异。(通过“推”与“拉”,我指的是数据流的方向。.NET和C#的响应式编程技术
这是一篇非常不错的文章,详细介绍了语句lambda和表达式lambda之间的区别,并更深入地讨论了表达式tress的概念:复习C#委托,表达式树和lambda语句与lambda表达式。”。
我们使用IEnumerable
和IQueryable
操作从数据库检索的数据。IQueryable
继承自IEnumerable
,因此IQueryable
包含所有IEnumerable
功能。IQueryable
和之间的主要区别IEnumerable
是IQueryable
使用过滤器执行查询,而先IEnumerable
执行查询,然后根据条件过滤数据。
在下面找到更多详细的区别:
IEnumerable
IEnumerable
存在于System.Collections
命名空间中IEnumerable
在服务器端执行选择查询,在客户端加载内存中的数据,然后过滤数据IEnumerable
适合查询列表,数组等内存中的数据IEnumerable
有利于LINQ to Object和LINQ to XML查询可查询
IQueryable
存在于System.Linq
命名空间中IQueryable
使用所有过滤器在服务器端执行“选择查询”IQueryable
适用于查询内存外(例如远程数据库,服务)集合中的数据IQueryable
有利于LINQ to SQL查询因此IEnumerable
,通常用于处理内存中的集合,而IQueryable
通常用于操纵集合。
IEnumerable和IQueryable都用于保存数据集合并执行数据操作操作,例如对数据集合进行过滤。在这里您可以找到最佳的差异比较示例。 http://www.gurujipoint.com/2017/05/difference-between-ienumerable-and.html