EF 三种加载方式

EF 三种加载方式
一、定义
二、通过日志查看ef执行过程中的语句
三、延迟加载、懒加载(Lazy Loading)
四、立即加载、贪婪加载、预加载(Eager Loading)
五、显示加载(Explicit Loading)
一、定义
EF数据加载三种方式:延迟加载、饥饿加载、显示加载(EF中默认是开启延迟加载)

延迟加载(Lazy Loading) 和淘宝的商品列表一样,下拉刷新,按需加载。
饥饿加载 (Eager Loading) 加载父对象时同时加载子对象。
显式加载 (Explicitly Loading)当我们禁用了延迟加载,仍然可以通过显式加载来延迟加载相关实体。
二、通过日志查看ef执行过程中的语句
    WebCenterContext db = new WebCenterContext();
    // 监听日志,将与数据库之间的每一步操作都会打印出来
    db.Database.Log =s=> {
        DataOperate.Logs.LogsWrite.WriteLogToFile("EF_SQL",s,"");
    };

三、延迟加载、懒加载(Lazy Loading)
特别注意:关闭延迟加载后,查询主表数据时候,主表的中从表实体为null。

全局配置:在数据库上下文的构造方法中添加 this.Configuration.LazyLoadingEnabled = true;
也可以在使用的时候单独配置。
延迟加载 true:开启,false:关闭,默认就是延迟加载的。
延迟加载的数据在使用的时候才会加载出来,在循环遍历数据的时候建议使用延迟加载。
每次调用子实体(外键所在的实体)的时候,才去查询数据库. 主表数据加载的时候,不去查询外键所在的从表。
需要满足的条件:
①:poco类是public且不能为sealed;
②:关联属性需要标记为Virtual;
开启延迟加载的状态:

using (WebCenterContext db = new WebCenterContext())
{
    db.Database.Log = Console.WriteLine;
    //EF默认就是延迟加载,默认下面的语句就是true,所以下面语句注释没有任何影响
    //db.Configuration.LazyLoadingEnabled = true;
    var list = db.UserInfo.ToList();  //此处加载的数据,根据监测得出结论,没有对从表进行任何查询操作
    foreach (var user in list)
    {
        Console.WriteLine("编号:{0},姓名:{1}", user.Code, user.Name);
        //下面调用导航属性(一对一的关系)  每次调用时,都要去查询数据库(查询从表)
        var login = user.LoginInfo;
        Console.WriteLine("登陆时间:{0},IP地址:{1}", login.LoginTime, login.IP);
    }
}

关闭延迟加载的状态:

using (WebCenterContext db = new WebCenterContext())
{
    try
    {
        db.Database.Log = Console.WriteLine;
        //下面的语句为关闭延迟加载
        db.Configuration.LazyLoadingEnabled = false;
        var list = db.UserInfo.ToList();  //关闭延迟加载后,此处从表实体LoginInfo为null,后面不会再次查询了
        foreach (var user in list)
        {
            Console.WriteLine("学生编号:{0},学生姓名:{1}", user.Code, user.Name);
            //login 为null,不会再次查询数据库,所以此处报错
            var login = user.LoginInfo;
            Console.WriteLine("登陆时间:{0},IP地址:{1}", login.LoginTime, login.IP);
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}

四、立即加载、贪婪加载、预加载(Eager Loading)
使用步骤:
①:先关闭延迟加载:db.Configuration.LazyLoadingEnabled = false;
②:查询主表的同时通过Include把从表数据也查询出来;
由于查询主表的时候通过Include已经一次性将数据查询了出来,所以在调用从表数据的时候,均从缓存中读取,无须查询数据库。
using (WebCenterContext db = new WebCenterContext())
{
    db.Database.Log = Console.WriteLine;
    //1.关闭延迟加载
    db.Configuration.LazyLoadingEnabled = false;
    //2. 获取主表数据的同时,通过Include将从表中的数据也全部加载出来
    var list = db.UserInfo.Include("LoginInfo").ToList();
    foreach (var user in list)
    {
        Console.WriteLine("编号:{0},姓名:{1}", user.Code, user.Name);

        //这里获取从表中的数据,均是从缓存中获取,无需查询数据库
        var login = user.LoginInfo;
        Console.WriteLine("登陆时间:{0},IP地址:{1}", login.LoginTime, login.IP);
    }
}

五、显示加载(Explicit Loading)
关闭延迟加载后,单纯查询主表的数据,后面又想再次查询从表,这个时候就需要用到显示加载了。
前提:
①:关闭了延迟加载:db.Configuration.LazyLoadingEnabled = false;
②:单纯查询了主表,没有使用Include函数关联查询从表;
使用步骤:
①:单个实体用:Reference;
②:集合用:Collection;
③:最后需要Load一下;
using (WebCenterContext db = new WebCenterContext())
{
    db.Database.Log = Console.WriteLine;
    //1.关闭延迟加载
    db.Configuration.LazyLoadingEnabled = false;

    //2.此处加载的数据,不含从表中的数据
       var list = db.UserInfo.ToList();
      foreach (var user in list)
     {
        Console.WriteLine("编号:{0},姓名:{1}", user.Code, user.Name);

        //3.下面的这句话,可以开启重新查询一次数据库
        //3.1 单个属性的情况用Refercence
        db.Entry<UserInfo>(user).Reference(c => c.LoginInfo).Load();
        //3.2 集合的情况用Collection
        //db.Entry<UserInfo>(user).Collection(c => c.LoginInfo).Load();
        
        //下面调用关联属性(一对一的关系)  每次调用时,都要去查询数据库
        var login = a.LoginInfo;
        Console.WriteLine("登陆时间:{0},IP地址:{1}", login.LoginTime, login.IP);
    }

}

 

posted on 2021-04-01 23:05  itjeff  阅读(405)  评论(0编辑  收藏  举报

导航