zoukankan      html  css  js  c++  java
  • IEnumerable和IQueryable和Linq的查询

    IEnumerable和IEnumerable

    1.IEnumerable查询必须在本地执行.并且执行查询前我们必须把所有的数据加载到本地.而且更多的时候.加载的数据有大量的数据是我们不需要的无效数据.但是我们却不得不传输更多的数据.做更多的无用功。
    使用IEnumerable,所有对于IEnumerable的过滤,排序等操作,都是在内存中发生的。也就是说数据已经从数据库中获取到了内存中,只是在内存中进行过滤和排序操作。

    2.IQueryable却总能只提供你所需要的数据.大大减少了数据的传输
    IQueryable的优势是它有表达式树,所有对于IQueryable的过滤,排序等操作,都会先缓存到表达式树中,只有当真正遍历发生的时候,才会将表达式树由IQueryProvider执行获取数据操作。

    总结:IEnumerable总是先把所有数据从数据库加载到本地内存中,才开始执行过滤,排序等操作

    IQueryable总是将过滤,排序等操作缓存到表达式树种,发生正真的遍历的时候才会执行表达式树获取所需要的数据

    Linq查询中的IEnumerable和IEnumerable

    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<>。

     1 using (var context = new NorthwindEntities())
     2 {
     3    var orderTmp =context.Orders.Where(p=>p.CustomerID=="RATTC");
     4 
     5    var orders = orderTmp.Where(p => p.OrderDate > new DateTime(1997, 1, 1));
     6 
     7    foreach (var order in orders)
     8    {
     9       Console.WriteLine("OrderId:" + order.OrderID);
    10    }
    11 }

    通过vs的Intellisense我们可以看到Where的返回类型为IQueryable,参数是Expression类型的:

    我们再看一下这一段代码:

     1 using (var context = new NorthwindEntities())
     2 {
     3     var orderTmp = context.Orders.Where(p => p.CustomerID == "RATTC").AsEnumerable();
     4 
     5     var orders = orderTmp.Where(p => p.OrderDate > new DateTime(1997, 1, 1));
     6 
     7     foreach (var order in orders)
     8     {
     9         Console.WriteLine("OrderId:" + order.OrderID);
    10     }
    11 }

    这段代码的不同在于我们将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个建议》。

  • 相关阅读:
    STDMETHOD (转)
    DirectX中的纹理映射相关技术 (转)
    (转)清空std::stringstream,联系到stream的clear()和清空
    (转载)MultiAnimation
    (转)SkyBox
    [转载]漫谈游戏中的阴影技术
    反射矩阵计算
    (转)COM组件里的AddRef()
    LINQ简记(2):重要概念
    继续聊WPF——自定义命令
  • 原文地址:https://www.cnblogs.com/abc1069/p/4004477.html
Copyright © 2011-2022 走看看