LINQ查询中的IEnumerable和IQueryable

LINQ查询方法一共提供了两种扩展方法,在System.Linq命名空间下,有两个静态类:Enumerable类,它针对继承了IEnumerable<T>接口的集合进行扩展;Queryable类,针对继承了IQueryable<T>接口的集合进行扩展。咱们会发现接口IQueryable<T>实际也是继承了IEnumerable<T>接口的,既然这样微软为何要设计出两套扩展方法呢?sql

从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>?spa

首先咱们来看一下LINQ to SQL的代码:设计

using (var context = new NorthwindEntities()) 3d

{ blog

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

}

}

 

这段代码的不一样在于咱们将LINQ的查询返回IEnumerable类型,咱们看一下vs的Intellisense效果:

因为咱们在LINQ查询的时候加上了AsEnumerable(),所以咱们在第二条语句能看到返回类型已经变为IEnumerable,参数也变成了Func<>类型。

至于这两段代码到底有什么区别,咱们分别执行代码,在sql profiler里看一下生成的sql语句:

第一段代码效果:

虽然咱们使用两条语句进行了查询,但最终只生成了一条SQL语句,将查询参数合并了。

第二代码效果:

这一次咱们依然只看到一条SQL语句,但查询条件也只有一个,但两次查询的结果是一致。

 

缘由在于Func<>直接会被编译器编译成IL代码,可是Expression<>只是存储了一个表达式树,在运行期做处理,LINQ to SQL最终会将表达式树转为相应的SQL语句,而后在数据库中执行

如今咱们应该知道什么时候使用IEnumerable<T>,什么时候使用Iqueryable<T>。

 

以上内容部分参考《编写高质量代码改善C#程序的157个建议》。

相关文章
相关标签/搜索