IEnumerable<T>和IQueryable<T>区分
2014-10-24 06:53
405 查看
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的代码:
通过vs的Intellisense我们可以看到Where的返回类型为IQueryable,参数是Expression类型的:
![](http://images.cnitblog.com/blog/85528/201408/221731104404602.png)
我们再看一下这一段代码:
这段代码的不同在于我们将LINQ的查询返回IEnumerable类型,我们看一下vs的Intellisense效果:
![](http://images.cnitblog.com/blog/85528/201408/221731106908145.png)
由于我们在LINQ查询的时候加上了AsEnumerable(),因此我们在第二条语句能看到返回类型已经变为IEnumerable,参数也变成了Func<>类型。
至于这两段代码到底有什么区别,我们分别执行代码,在sql profiler里看一下生成的sql语句:
第一段代码效果:
![](http://images.cnitblog.com/blog/85528/201408/221731110184946.png)
虽然我们使用两条语句进行了查询,但最终只生成了一条SQL语句,将查询参数合并了。
第二代码效果:
![](http://images.cnitblog.com/blog/85528/201408/221731112688489.png)
这一次我们依然只看到一条SQL语句,但查询条件也只有一个,但两次查询的结果是一致。
原因在于Func<>直接会被编译器编译成IL代码,但是Expression<>只是存储了一个表达式树,在运行期作处理,LINQ to SQL最终会将表达式树转为相应的SQL语句,然后在数据库中执行。
现在我们应该知道何时使用IEnumerable<T>,何时使用Iqueryable<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); } } |
![](http://images.cnitblog.com/blog/85528/201408/221731104404602.png)
我们再看一下这一段代码:
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); } } |
![](http://images.cnitblog.com/blog/85528/201408/221731106908145.png)
由于我们在LINQ查询的时候加上了AsEnumerable(),因此我们在第二条语句能看到返回类型已经变为IEnumerable,参数也变成了Func<>类型。
至于这两段代码到底有什么区别,我们分别执行代码,在sql profiler里看一下生成的sql语句:
第一段代码效果:
![](http://images.cnitblog.com/blog/85528/201408/221731110184946.png)
虽然我们使用两条语句进行了查询,但最终只生成了一条SQL语句,将查询参数合并了。
第二代码效果:
![](http://images.cnitblog.com/blog/85528/201408/221731112688489.png)
这一次我们依然只看到一条SQL语句,但查询条件也只有一个,但两次查询的结果是一致。
原因在于Func<>直接会被编译器编译成IL代码,但是Expression<>只是存储了一个表达式树,在运行期作处理,LINQ to SQL最终会将表达式树转为相应的SQL语句,然后在数据库中执行。
现在我们应该知道何时使用IEnumerable<T>,何时使用Iqueryable<T>。
相关文章推荐
- IEnumerable<T>和IQueryable<T>区分
- IEnumerable<T>与IQueryable<T>以及.net的扩展方法
- LINQ : IEnumerable<T> and IQueryable<T>区别
- 写一个针对IQueryable<T>的扩展方法支持动态排序
- 再讲IQueryable<T>,揭开表达式树的神秘面纱
- IQueryable<T>获取查询计划(SQL)
- 【转】再讲IQueryable<T>,揭开表达式树的神秘面纱
- Understanding the implications of IQueryable<T>
- 通过IQueryable<T>获得DbContext
- 编写高质量代码改善C#程序的157个建议[IEnumerable<T>和IQueryable<T>、LINQ避免迭代、LINQ替代迭代]
- 【转载】MVC分页控件之二,为IQueryable定义一个扩展方法,直接反回PagedList<T>结果集
- IQueryable<T>和IEnumerable<T>的区别
- 将不确定变为确定~DAL层向BLL层返回数据用IEnumerable<T>还是IQueryable<T>
- 返回 IQueryable<T> OR List<T>
- IQueryable<T> 与 ObjectQuery<T> 差异
- 编写高质量代码改善C#程序的157个建议[IEnumerable<T>和IQueryable<T>、LINQ避免迭代、LINQ替代迭代]
- C#根据日期范围过滤IQueryable<T>集合
- Entity Framework DbSet<T>之Include方法与IQueryable<T>扩展方法Include的使用
- understanding iqueryable<T>
- Entity Framework中使用IEnumerable<T>、IQueryable<T>及IList<T>的区别