EF 三种加载方式

本文介绍了EF Core中的三种数据加载方式:延迟加载(LazyLoading)如何工作,如何通过日志观察SQL语句,以及贪婪加载(EagerLoading)和显式加载(ExplicitLoading)的区别与应用场景。了解这些技巧能有效提升应用性能和数据库查询优化。
摘要由CSDN通过智能技术生成

一、定义

EF数据加载三种方式:延迟加载饥饿加载显示加载EF中默认是开启延迟加载

  1. 延迟加载(Lazy Loading) 和淘宝的商品列表一样,下拉刷新,按需加载。
  2. 饥饿加载 (Eager Loading) 加载父对象时同时加载子对象。
  3. 显式加载 (Explicitly Loading)当我们禁用了延迟加载,仍然可以通过显式加载来延迟加载相关实体。

二、通过日志查看ef执行过程中的语句

	WebCenterContext db = new WebCenterContext();
	// 监听日志,将与数据库之间的每一步操作都会打印出来
	db.Database.Log =s=> {
	    DataOperate.Logs.LogsWrite.WriteLogToFile("EF_SQL",s,"");
	};

三、延迟加载、懒加载(Lazy Loading)

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

  1. 全局配置:在数据库上下文的构造方法中添加 this.Configuration.LazyLoadingEnabled = true;
  2. 也可以在使用的时候单独配置。
  3. 延迟加载 true:开启,false:关闭,默认就是延迟加载的。
  4. 延迟加载的数据在使用的时候才会加载出来,在循环遍历数据的时候建议使用延迟加载。
  5. 每次调用子实体(外键所在的实体)的时候,才去查询数据库. 主表数据加载的时候,不去查询外键所在的从表。
  6. 需要满足的条件:
    ①: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)

  1. 使用步骤:
    ①:先关闭延迟加载:db.Configuration.LazyLoadingEnabled = false;
    ②:查询主表的同时通过Include把从表数据也查询出来;
  2. 由于查询主表的时候通过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)

  1. 关闭延迟加载后,单纯查询主表的数据,后面又想再次查询从表,这个时候就需要用到显示加载了。
  2. 前提:
    ①:关闭了延迟加载:db.Configuration.LazyLoadingEnabled = false;
    ②:单纯查询了主表,没有使用Include函数关联查询从表;
  3. 使用步骤:
    ①:单个实体用: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);
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值