What is the difference between IQueryable<T> and IEnumerable<T>?
另请参见与此问题重叠的iQuery和IEnumerable之间的区别。
首先,
表达式可以是对象本身的常量表达式,也可以是由一组查询运算符和操作数组成的更复杂的树。调用查询提供程序的
主要的区别在于,
IEnumerable 非常适合处理在内存中迭代的序列,但是IQueryable 允许内存不足的事情,如远程数据源,如数据库或Web服务。
查询执行:
如果查询的执行将"进行中",通常只需要执行查询的每个部分的代码(作为代码)。
如果执行将在进程外执行,则必须以数据表示查询逻辑,以便LINQ提供程序可以将其转换为内存不足执行的适当形式-无论是LDAP查询、SQL还是其他任何形式。
更多在:
- Linq:
IEnumerable 和IQueryable 。 - C 3.0和LINQ。
- "返回
IEnumerable 对IQueryable " - 面向.NET和C开发人员的反应式编程-介绍
IEnumerable 、IQueryable 、IObservable 和IQbservable 。
这是YouTube上的一个很好的视频,它展示了这些界面的不同之处,值得一看。
下面是一个很长的描述性答案。
要记住的第一点是
有很多不同之处,但让我们来讨论一个最大的不同之处。当使用
考虑下面的简单代码,它使用带有实体框架的
1 2 3 | EmpEntities ent = new EmpEntities(); IEnumerable<Employee> emp = ent.Employees; IEnumerable<Employee> temp = emp.Where(x => x.Empid == 2).ToList<Employee>(); |
在客户机端执行过滤器,其中
但是现在看到下面的代码,我们已经将
1 2 3 | EmpEntities ent = new EmpEntities(); IQueryable<Employee> emp = ent.Employees; IQueryable<Employee> temp = emp.Where(x => x.Empid == 2).ToList<Employee>(); |
因此,
因此,如果您只使用内存中的数据收集
IEnumerable:IEnumerable最适合处理内存中的集合(或本地查询)。IEnumerable不在项之间移动,它是仅转发的集合。
IQueryable:iQuery最适合远程数据源,如数据库或Web服务(或远程查询)。iQueryable是一个非常强大的功能,它支持各种有趣的延迟执行场景(如分页和基于组合的查询)。
因此,当必须简单地迭代内存中的集合时,请使用IEnumerable,如果需要对集合(如数据集和其他数据源)执行任何操作,请使用iQuery
简单来说,另一个主要区别是IEnumerable在服务器端执行select查询,在客户端将数据加载到内存中,然后过滤数据,而iQueryable在服务器端使用所有过滤器执行select查询。
在现实生活中,如果您使用像linq to sql这样的ORM
- 如果您创建了一个IQueryable,那么查询可以转换为SQL并在数据库服务器上运行。
- 如果创建IEnumerable,那么在运行查询之前,所有行都将作为对象拉入内存。
在这两种情况下,如果您不调用
此外,如果扩展了您的查询:
1 | q.Where(x.name ="a").ToList() |
然后,对于iQuery,生成的SQL将包含"where name="a",但是对于IEnumerable,将从数据库中提取更多的角色,然后x.name="a"检查将由.net完成。
IEnumerable引用了一个集合,但iQueryable只是一个查询,它将在表达式树中生成。我们将运行此查询从数据库中获取数据。
下面提到的小测试可能有助于您理解
我在数据库(DDL脚本)中创建了以下结构:
1 | CREATE TABLE [dbo].[Employee]([PersonId] [int] NOT NULL PRIMARY KEY,[Salary] [int] NOT NULL) |
下面是记录插入脚本(DML脚本):
1 2 3 4 5 6 | 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 |
现在,我的目标是简单地从数据库中的
可查询路由代码:
1 2 3 4 5 6 7 8 9 10 | 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查询探查器会话,下面是执行摘要:
只是
IEnumerable路由的代码:
1 2 3 4 5 6 7 8 9 10 | 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); } } |
本案执行摘要:
FROM [dbo].[Employee] AS [Extent1]
现在的问题是,
这是我在一篇类似的文章(关于这个主题)上写的。(不,我通常不引用自己的话,但这些都是很好的文章。)
"这篇文章很有帮助:linq to sql中的iqueryable与ienumerable。
引用这篇文章,"根据msdn文档,通过构建内部表达式树来调用iQueryable。"这些扩展IQueryable(of T)的方法不直接执行任何查询。相反,它们的功能是构建表达式对象,该对象是表示累积查询的表达式树。""
表达式树是C和.NET平台上非常重要的结构。(一般来说,它们很重要,但C使它们非常有用。)为了更好地理解这一区别,我建议阅读官方C 5.0规范中表达式和语句之间的差异。对于分支到lambda微积分的高级理论概念,表达式支持将方法作为一级对象。iqueryable和IEnumerable之间的区别集中在这一点上。iqueryable构建表达式树,而IEnumerable不构建表达式树,至少对于我们这些不在微软秘密实验室工作的人来说不构建表达式树。
这是另一篇非常有用的文章,从推和拉的角度详细说明了不同之处。(通过"推"和"拉",我指的是数据流的方向。.NET和C的反应式编程技术#
这是一篇非常好的文章,详细介绍了语句lambda和表达式lambda之间的区别,并更深入地讨论了表达式tres的概念:重新访问c委托、表达式树和lambda语句与lambda表达式的比较。
我们使用IEnumerable和IQueryable来操作从数据库中检索到的数据。IEnumerable继承自IQueryable,因此IQueryable确实包含所有IEnumerable功能。iqueryable和IEnumerable的主要区别在于,iqueryable使用过滤器执行查询,而IEnumerable首先执行查询,然后根据条件过滤数据。
在下面找到更详细的区别:
可枚举的
可查询的
因此,IEnumerable通常用于处理内存中的集合,而iQueryable通常用于操作集合。
IEnumerable和IQueryable都用于保存数据收集,并执行数据操作操作操作,例如对数据收集进行筛选。在这里,您可以找到与示例的最佳差异比较。http://www.gurujipoint.com/2017/05/difference-between-ienumerable-and.html
如果我们处理来自数据库的大量数据,iqueryable比iEnumerable更快,因为iqueryable只从数据库中获取所需数据,而iEnumerable从数据库中获取所有数据,而不管是否需要。
IEnumerable:当我们想要处理进程内内存时,即不需要数据连接iqueryable:何时处理SQL Server,即数据连接ilist:添加对象、删除对象等操作