zoukankan      html  css  js  c++  java
  • IQuerable与IEnumable的区别

    核心区别:

    IQueryable该接口会把查询表达式先缓存到表达式树Expression 中,只有当真正用到数据的时候(例如 遍历 ),才会由IQueryProvider解析表达式树,生成sql语句执行数据库查询操作。(离线集合)

    IEnumable 公开枚举器,该枚举器支持在指定类型的集合上进行简单迭代。也就是说:实现了此接口的object,就可以直接使用foreach遍历此object;(本地集合)

    (1)所有对于IEnumerable的过滤,排序等操作,都是在内存中发生的。也就是说数据已经从数据库中获取到了内存中,只是在内存中进行过滤和排序操作。

    (2)所有对于IQueryable的过滤,排序等操作,只有在数据真正用到的时候才会到数据库中查询。这也是Linq的延迟加载核心所在。

    案例一:

    先上代码

    [csharp] view plain copy
     
    1. private void Form1_Load(object sender, EventArgs e)  
    2. {  
    3.     using (DemoContext context = new DemoContext())  
    4.     {  
    5.         var customer = context.cunstomer.Where(c => c.Name == "牡丹");  
    6.         foreach (var item in customer)  
    7.         {  
    8.             MessageBox.Show(item.Id.ToString());  
    9.         }  
    10.     }  
    11. }  

    至于代码中的上下文定义以及实体集大家不必纠结,我们在这里要透过表象看本质。在上面的程序中添加断点,同时启动sql server profiler监视工具,运行程序。

    程序会在断点处停下来,如下所示

    上面只是到点断点处,当然断点处的语句还有执行,继续单步执行。

    执行过断点处所在的语句,观察监视工具还是什么都没有。

    咦,是不是出什么问题了呢?为什么没有查询语句执行呢?真的是监视工具出问题了吗?

    继续单步调试

    咦,这个时候怎么出现sql查询语句了。很奇怪吧,这就是ado.net EF的延迟加载技术,这里面很重要的一部分就是通过IQueryable接口实现的(具体我们放到最后再说)。

    讲过了Queryable类的Where方法,接下来我们再来看一下Enumable类的Where方法。

    修改上面的代码如下所示

    [csharp] view plain copy
     
    1. private void Form1_Load(object sender, EventArgs e)  
    2. {  
    3.     using (DemoContext context = new DemoContext())  
    4.     {  
    5.         var customer = context.cunstomer.Where(c => c.Name == "牡丹").AsEnumerable();  
    6.         foreach (var item in customer)  
    7.         {  
    8.             MessageBox.Show(item.Id.ToString());  
    9.         }  
    10.     }  
    11. }  

    同样是打开监视工具,添加断点,运行程序

    单步调试,继续运行

    执行过断点所在的语句及执行了查询语句。

    关于上面的两个测试总结如下。

    (1)所有对于IEnumerable的过滤,排序等操作,都是在内存中发生的。也就是说数据已经从数据库中获取到了内存中,只是在内存中进行过滤和排序操作。

    (2)所有对于IQueryable的过滤,排序等操作,只有在数据真正用到的时候才会到数据库中查询。这也是Linq的延迟加载核心所在。

    案例二:

                //linq 表达式的返回值的类型是IQueryable
                IQueryable<HKSJ_USERS> temp = from u in dbContext.HKSJ_USERS
                           where u.ID > 4
                           select u;
                //初始化了一下IQueryable接口里面的三个参数作用:
                // 1 linq表达式转成表达式树Expression
                // 2 给元素类型 Type ElementType赋值,这里指的是<HKSJ_USERS>
                // 3 给提供者IQueryProvider Provider赋值,这里是efProvider,若是XML那就是xmlProvider,若是string 就stringProvider
             所以理论上linq可以无限扩展。
    //当用到 IQueryable接口的集合的数据的时候,provider解析Expression然后获取相应的数据。进行遍历执行。 //linq to ef:查询是在数据库端进行过滤。 foreach (var hksjUsers in temp) { Console.WriteLine(hksjUsers.ID + " " + hksjUsers.UserName); } //IEnumable内存里面过滤:把数据库中的所有的数据都查询到程序里面来之后,再进行过滤。 //linq to object var demoList = from u in dbContext.HKSJ_USERS.AsIEnumable() //ToList() where u.ID > 4 select u; foreach (var hksjUsers in demoList) { }
           
             //List集合、Arrary,Dictionary,....都继承与IEnumable接口。

    案例三

                    //查询的结果放入IQueryable接口的集合中
                    IQueryable<T_Class> classesIQue = (from c in schoolEntities.T_Class
                                                       orderby c.ID
                                                         select c).Skip<T_Class>(3).Take<T_Class>(3);
                    //注意这个AsEnumerable<T_Class>()在分页查询之前,先将其转换成IEnumerable类型
                    IEnumerable<T_Class> classesIEnu = (from c in schoolEntities.T_Class
                                                        orderby c.ID   
                                                        select c).AsEnumerable<T_Class>().Skip<T_Class>(3).Take<T_Class>(3);
    

      

    IQueryable接口(F12查看)

    namespace System.Linq
    {
        public interface IQueryable : IEnumerable
        {
            Type ElementType { get; }
            Expression Expression { get; }
            IQueryProvider Provider { get; }
        }
    }

     

    IEnumerable接口(F12查看)

    namespace System.Collections
    {
        //
        // 摘要:
        //     Exposes an enumerator, which supports a simple iteration over a non-generic collection.To
        //     browse the .NET Framework source code for this type, see the Reference Source.
        [ComVisible(true)]
        [Guid("496B0ABE-CDEE-11d3-88E8-00902754C43A")]
        public interface IEnumerable
        {
            //
            // 摘要:
            //     Returns an enumerator that iterates through a collection.
            //
            // 返回结果:
            //     An System.Collections.IEnumerator object that can be used to iterate through
            //     the collection.
            [DispId(-4)]
            IEnumerator GetEnumerator();
        }
    }
    namespace System.Collections
    {
        //
        // 摘要:
        //     Supports a simple iteration over a non-generic collection.
        [ComVisible(true)]
        [Guid("496B0ABF-CDEE-11d3-88E8-00902754C43A")]
        public interface IEnumerator
        {
            //
            // 摘要:
            //     Gets the current element in the collection.
            //
            // 返回结果:
            //     The current element in the collection.
            object Current { get; }
    
            //
            // 摘要:
            //     Advances the enumerator to the next element of the collection.
            //
            // 返回结果:
            //     true if the enumerator was successfully advanced to the next element; false if
            //     the enumerator has passed the end of the collection.
            //
            // 异常:
            //   T:System.InvalidOperationException:
            //     The collection was modified after the enumerator was created.
            bool MoveNext();
            //
            // 摘要:
            //     Sets the enumerator to its initial position, which is before the first element
            //     in the collection.
            //
            // 异常:
            //   T:System.InvalidOperationException:
            //     The collection was modified after the enumerator was created.
            void Reset();
        }
    }

    参考:

    https://blog.csdn.net/ydm19891101/article/details/50969323

  • 相关阅读:
    FineUI开源版(ASP.Net)初学手册-部分JS整理
    ASP.NET-FineUI开发实践-15
    ASP.NET-FineUI开发实践-14
    FineUI开源版(ASP.Net)开发实践-目录
    ASP.NET-FineUI开发实践-13(二)
    ASP.NET-FineUI开发实践-13(一)
    在VS.NET中根据条件设置不同的MainForm
    VB.NET在基类中定义共享事件(类似于C#中的静态事件)
    也谈解决Combobox绑定数据后取值出现System.Data.DataRowView的问题
    在SQL Server 2014下面使用的SQL2000的Northwind和Pubs示例数据库
  • 原文地址:https://www.cnblogs.com/hao-1234-1234/p/9125246.html
Copyright © 2011-2022 走看看