• 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);
        }
    
    }
    
  • 相关阅读:
    CFileDialog打开多个文件失败 返回错误 FNERR_BUFFERTOOSMALL
    VC 控件集合
    [摘]思科认证三步走及找工作的七大职业走向
    windows无法配置此无线连接解决办法
    VS 2019 项目添加引用,提示:对COM组件的调用返回了错误HRESULT E_FAIL
    c# winform 获取当前程序运行根目录
    DataGridView 转换成 DataTable
    SQL Server日志文件过大 大日志文件清理方法 不分离数据库
    行动吧!让自己骚起来
    抖音很火的3D旋转相册 (源代码分享)
  • 原文地址:https://www.cnblogs.com/itjeff/p/14608678.html
Copyright © 2020-2023  润新知