• EF的延迟加载


    什么是延迟加载?
    通俗的是说,就是按需要加载,也就是需要数据的时候再加载EF默认会进行延迟加载

    为什么要使用延迟加载?
    你的身边是不是有朋友在使用EF开发的时候总是喜欢在每一句的后面加上一个ToList(),
    其实这样是不对的!
    在每次执行ToList()或者FirstOrDefault()等函数操作时,EF都会去请求一次数据库。
    这里说的是数据查询操作,至于CUD这些操作会在SaveChange()时进行数据库的请求
    比如这样一段代码:(仅举例)

    var users = EntityTest.Users.Where(u=>u.Adress=="湖北");//过滤地址为湖北的
    var userMale = users.Where(u=>u.gender==1).ToList();//过滤出性别为男的
    var userFemale = users.Where(u=>u.gender==0).ToList();//过滤出性别为女的
    

    在过滤湖北的这一行,其实并没有进行数据库的请求,只是Where方法将所写的lambda表达式保存为了Sql语句,在进行性别过滤进行ToList()之后才访问了数据库。
    好处:用时才加载,保证了数据的实时性,另外在做多条件查询时只要是先拼凑查询语句,最后再执行数据库访问,降低了服务器的负担。

    延迟加载的实现:
    上面说到,Where方法将所写的lambda表达式保存为了Sql语句,通过智能提示,发现此时users返回的是一个IQueryable类型的数据,并且Where的第一个参数是this前缀,
    由此得出Where并不是在IQueryable接口内部的,而是在外部类通过扩展方法的方式加上去的,这个类就是Queryable

    但是为何Where方法是从Entity这个EF上下文对象中点出来的?
    通过F2进入EF上下文中的DbSet 查看 , 原来是继承了IQueryable接口

    因此,EF的延迟加载是依靠Queryable实现的

    Queryable从何而来?
    在System.Linq命名空间下,有两个静态类:
    ①:Enumerable类,它针对继承了IEnumerable接口的集合进行扩展;
    ②:Queryable类,它针对继承了IQueryable接口的集合类进行扩展。接口IQueryable也是继承了IEnumerable接口的,所以,致使两个接口的方法在很大程度上时一致的。
    IEnumerable接口是本地内存中的数据读取,而IQueryable接口是远程数据的读取。
    如上所说IQueryable中的Where是将表达式保存为Sql,IEnumerable接口中的Where就是用来过滤本地数据的。

    实现步骤:
    每次在执行where查询操作符的时候IQueryProvider会为我们创建一个新的IQueryable,调用AsEnumerable()方法的时候并不会去实际取值,只是
    得到了一个IEnumerable,所以EF在查询数据时候不要先取IEnumerable再去筛选数据。执行ToList方法时才会去真正调用迭代器GetEnumerator()
    取值。真正取值时候,会去执行IQueryProvider中的Excute方法.(解析表达式,然后执行取得结果))
    这就是IQueryable的延迟加载

  • 相关阅读:
    【尺取法】
    [USACO12MAR]花盆Flowerpot [单调队列]
    数据库笔记
    NYOJ 91 阶乘之和(贪心)
    NYOJ 71 独木舟上的旅行(贪心)
    水池数目(DFS)
    poj 1164城堡问题(DFS)
    NYOJ 12 喷水装置(二)( 贪心)
    NYOJ 6(贪心)
    NYOJ 45( 分治,大数)
  • 原文地址:https://www.cnblogs.com/bemad/p/14638110.html
Copyright © 2020-2023  润新知