MVC5 中IQueryable 与 IEnumerable
- IQueryable 是在把筛选的条件都转为SQL语句在数据库查询时直接筛选。
- IEnumerable 是在数据库中把整张表查出来保存在内存中,再进行筛选。
- IEnumerable<T>泛型类是在skip take之前就已经加载到内存中了,而IQueryable<T>是将skip,take翻译成SQL语句之后,在实际使用数据时候才发命令给数据库
所以,在数据层都用IQueryable接口,而在业务层再将其转换成IEnumerable接口
使用MiniProfiler来检测,会发现两者的区别
使用IEnumerable检测发现,它在数据库中执行的语句是: (读取返回完整模型类Model)※※※※※※
SELECT [Extent].[Id] AS [Id], [Extent].[Name] AS [Name], [Extent].[Department] AS [Department] FROM [dbo].[Employee] AS [Extent]
可见,它从数据库中取出了所有数据。然后在内存中再筛选.
使用IQueryable检测发现,它在数据库中执行的语句是:(读取返回筛选后模型类Model)※※※※※※
SELECT TOP (2) [Extent].[Id] AS [Id], [Extent].[Name] AS [Name], [Extent].[Department] AS [Department] FROM [dbo].[Employee] AS [Extent]
可见,它只从数据库中取出了两条数据
一、LINQ查询方法一共提供了两种扩展方法,在System.Linq命名空间下,有两个静态类:
- Enumerable类,它针对继承了IEnumerable<T>接口的集合进行扩展;
- Queryable类,针对继承了IQueryable<T>接口的集合进行扩展。
二、我们会发现接口IQueryable<T>实际也是继承了IEnumerable<T>接口的,既然这样微软为什么要设计出两套扩展方法呢?
从LINQ查询功能上我们知道实际上可以分为三类:
- LINQ to OBJECTS、
- LINQ to SQL
- LINQ to XML。
其实为设计这两套接口主要是针对LINQ to OBJECTS和LINQ to SQL,两者对于查询的内部处理机制是完全不同的。
- 针对LINQ to OBJECTS 时,使用Enumerable中的扩展方法对本地集合进行排序和查询操作,查询参数接受的是Func<>,Func<>叫做谓语表达式,相当于一个委托。
- 针对LINQ to SQL时,则使用Queryable中的扩展方法,它接受的是Expression<>。
三、那么,到底什么时候使用IQueryable<T>,什么时候使用IEnumerable<T>?
首先我们来看一下LINQ to SQL的代码:
using (var context = new NorthwindEntities()) { var orderTmp = context.Orders.Where(p=>p.CustomerID=="RATTC"); var orders = orderTmp.Where(p => p.OrderDate > new DateTime(1997, 1, 1)); foreach (var order in orders) { Console.WriteLine("OrderId:" + order.OrderID); } }
通过vs的Intellisense我们可以看到Where的返回类型为IQueryable,参数是Expression类型的:
我们再看一下这一段代码:
using (var context = new NorthwindEntities()) { var orderTmp = context.Orders.Where(p => p.CustomerID == "RATTC").AsEnumerable(); var orders = orderTmp.Where(p => p.OrderDate > new DateTime(1997, 1, 1)); foreach (var order in orders) { Console.WriteLine("OrderId:" + order.OrderID); } }
看一下vs的Intellisense效果:
由于我们在LINQ查询的时候加上了AsEnumerable(),因此我们在第二条语句能看到返回类型已经变为IEnumerable,参数也变成了Func<>类型。
至于这两段代码到底有什么区别,我们分别执行代码,在sql profiler里看一下生成的sql语句:
第一段代码效果:
![](https://img2018.cnblogs.com/blog/344147/201904/344147-20190406152741023-1754363688.png)
原因在于Func<>直接会被编译器编译成IL代码,但是Expression<>只是存储了一个表达式树,在运行期作处理,LINQ to SQL最终会将表达式树转为相应的SQL语句,然后在数据库中执行。
现在我们应该知道何时使用IEnumerable<T>,何时使用Iqueryable<T>。建议延迟加载数据使用Iqueryable<T>。
转:https://www.cnblogs.com/chenh/p/10661917.html