第六节: EF高级属性(二) 之延迟加载、立即加载、显示加载(含导航属性)
2017-10-26 21:52
330 查看
一. 简介
上一个章节中,也介绍了立即加载和延迟加载,但上一个章节是针对单表而言的,不含外键,立即也好,延迟也好,都是指单表中的数据。但本章节重点介绍的三种加载方式均是针对含(导航属性、外键)的情况下,查询主表,从表中的数据加载情况。
下面准备两张表:Student和StudentAddress两张表,一对一 or 零 的关系,实体结构如下,通过CodeFirst来反向生成数据库。
二. Lazy Loading
1. 又名:延迟加载、懒加载
2. 需要满足的条件:
①:poco类是public且不能为sealed
②:导航属性需要标记为Virtual
满足以上两个条件,EF6默认就为延迟加载的模式。(默认:db.Configuration.LazyLoadingEnabled = true; )
3. 含义:每次调用子实体(外键所在的实体)的时候,才去查询数据库. 主表数据加载的时候,不去查询外键所在的从表。
4. 关闭延迟加载的办法: db.Configuration.LazyLoadingEnabled = false;
特别注意:关闭延迟加载后,查询主表数据时候,主表的中从表实体为null.
1. 延迟加载代码测试
2. 关闭延迟加载
三. Eager Loading
1. 又名:立即加载、贪婪加载、预加载
2. 使用步骤:
①:先关闭延迟加载:db.Configuration.LazyLoadingEnabled = false;
②:查询主表的同时通过Include把从表数据也查询出来:
3. 含义:由于查询主表的时候通过Include已经一次性将数据查询了出来,所以在调用从表数据的时候,均从缓存中读取,无须查询数据库
代码测试
四. Explicit Loading
1. 又名:显示加载
2. 背景:关闭延迟加载后,单纯查询主表的数据,后面又想再次查询从表,这个时候就需要用到显示加载了.
3. 前提:
①:关闭了延迟加载:db.Configuration.LazyLoadingEnabled = false;
②:单纯查询了主表,没有使用Include函数关联查询从表.
4. 使用步骤:
①:单个实体用:Reference
②:集合用:Collection
③:最后需要Load一下
5. 含义:关闭了延迟加载,单纯查询了主表数据,这个时候需要重新查询从表数据,就要用到显式加载了
代码测试
上一个章节中,也介绍了立即加载和延迟加载,但上一个章节是针对单表而言的,不含外键,立即也好,延迟也好,都是指单表中的数据。但本章节重点介绍的三种加载方式均是针对含(导航属性、外键)的情况下,查询主表,从表中的数据加载情况。
下面准备两张表:Student和StudentAddress两张表,一对一 or 零 的关系,实体结构如下,通过CodeFirst来反向生成数据库。
/// <summary> /// 学生表(一个学生只能有一个地址或没有地址) /// </summary> public class Student { public Student() { } public string studentId { get; set; } public string studentName { get; set; } public virtual StudentAddress StudentAddress { get; set; } }
/// <summary> /// 学生地址表(一个地址只能对应一个学生) /// </summary> public class StudentAddress { public StudentAddress() { } [ForeignKey("stu")] //特别注意这个地方,stu对应下面的 Student stu; //另外特别注意:studentAddressId,符合默认的Id生成规则,自动映射成主键,否则需要加【key】特性 public string studentAddressId { get; set; } public string addressName { get; set; } public virtual Student stu { get; set; } }
二. Lazy Loading
1. 又名:延迟加载、懒加载
2. 需要满足的条件:
①:poco类是public且不能为sealed
②:导航属性需要标记为Virtual
满足以上两个条件,EF6默认就为延迟加载的模式。(默认:db.Configuration.LazyLoadingEnabled = true; )
3. 含义:每次调用子实体(外键所在的实体)的时候,才去查询数据库. 主表数据加载的时候,不去查询外键所在的从表。
4. 关闭延迟加载的办法: db.Configuration.LazyLoadingEnabled = false;
特别注意:关闭延迟加载后,查询主表数据时候,主表的中从表实体为null.
1. 延迟加载代码测试
using (dbContext1 db = new dbContext1()) { Console.WriteLine("--------------------------- 01-延迟加载 -----------------------------"); db.Database.Log = Console.WriteLine; //EF默认就是延迟加载,默认下面的语句就是true,所以下面语句注释没有任何影响 //db.Configuration.LazyLoadingEnabled = true; var list = db.Student.ToList(); //此处加载的数据,根据监测得出结论,没有对从表进行任何查询操作 foreach (var stu in list) { Console.WriteLine("学生编号:{0},学生姓名:{1}", stu.studentId, stu.studentName); //下面调用导航属性(一对一的关系) 每次调用时,都要去查询数据库(查询从表) var stuAddress = stu.StudentAddress; Console.WriteLine("地址编号:{0},地址名称:{1}", stuAddress.studentAddressId, stu.studentName); } }
2. 关闭延迟加载
using (dbContext1 db = new dbContext1()) { try { Console.WriteLine("--------------------------- 02-关闭延迟加载 -----------------------------"); db.Database.Log = Console.WriteLine; //下面的语句为关闭延迟加载 db.Configuration.LazyLoadingEnabled = false; var list = db.Student.ToList(); //关闭延迟加载后,此处从表实体StudentAddress为null,后面不会再次查询了 foreach (var stu in list) { Console.WriteLine("学生编号:{0},学生姓名:{1}", stu.studentId, stu.studentName); //StudentAddress为null,不会再次查询数据库,所以此处报错 var stuAddress = stu.StudentAddress; Console.WriteLine("地址编号:{0},地址名称:{1}", stuAddress.studentAddressId, stu.studentName); } } catch (Exception ex) { Console.WriteLine(ex.Message); } }
三. Eager Loading
1. 又名:立即加载、贪婪加载、预加载
2. 使用步骤:
①:先关闭延迟加载:db.Configuration.LazyLoadingEnabled = false;
②:查询主表的同时通过Include把从表数据也查询出来:
3. 含义:由于查询主表的时候通过Include已经一次性将数据查询了出来,所以在调用从表数据的时候,均从缓存中读取,无须查询数据库
代码测试
using (dbContext1 db = new dbContext1()) { Console.WriteLine("--------------------------- 03-立即加载 -----------------------------"); db.Database.Log = Console.WriteLine; //1.关闭延迟加载 db.Configuration.LazyLoadingEnabled = false; //2. 获取主表数据的同时,通过Include将从表中的数据也全部加载出来 var list = db.Student.Include("StudentAddress").ToList(); foreach (var stu in list) { Console.WriteLine("学生编号:{0},学生姓名:{1}", stu.studentId, stu.studentName); //这里获取从表中的数据,均是从缓存中获取,无需查询数据库 var stuAddress = stu.StudentAddress; Console.WriteLine("地址编号:{0},地址名称:{1}", stuAddress.studentAddressId, stu.studentName); } }
四. Explicit Loading
1. 又名:显示加载
2. 背景:关闭延迟加载后,单纯查询主表的数据,后面又想再次查询从表,这个时候就需要用到显示加载了.
3. 前提:
①:关闭了延迟加载:db.Configuration.LazyLoadingEnabled = false;
②:单纯查询了主表,没有使用Include函数关联查询从表.
4. 使用步骤:
①:单个实体用:Reference
②:集合用:Collection
③:最后需要Load一下
5. 含义:关闭了延迟加载,单纯查询了主表数据,这个时候需要重新查询从表数据,就要用到显式加载了
代码测试
using (dbContext1 db = new dbContext1()) { Console.WriteLine("--------------------------- 04-显式加载 -----------------------------"); db.Database.Log = Console.WriteLine; //1.关闭延迟加载 db.Configuration.LazyLoadingEnabled = false; //2.此处加载的数据,不含从表中的数据 var list = db.Student.ToList(); foreach (var stu in list) { Console.WriteLine("学生编号:{0},学生姓名:{1}", stu.studentId, stu.studentName); //3.下面的这句话,可以开启重新查询一次数据库 //3.1 单个属性的情况用Refercence db.Entry<Student>(stu).Reference(c => c.StudentAddress).Load(); //3.2 集合的情况用Collection //db.Entry<Student>(stu).Collection(c => c.StudentAddress).Load(); //下面调用导航属性(一对一的关系) 每次调用时,都要去查询数据库 var stuAddress = stu.StudentAddress; Console.WriteLine("地址编号:{0},地址名称:{1}", stuAddress.studentAddressId, stu.studentName); } }
相关文章推荐
- 第五节: EF高级属性(一) 之 本地缓存、立即加载、延迟加载(不含导航属性)
- ASP.NET EF 延迟加载,导航属性延迟加载
- ASP.NET EF 延迟加载,导航属性延迟加载
- 《Entity Framework 6 Recipes》中文翻译系列 (22) -----第五章 加载实体和导航属性之延迟加载
- EF如何操作内存中的数据以及加载相关联表的数据:延迟加载、贪婪加载、显示加载
- 为导航属性关闭延迟加载
- EF如何操作内存中的数据以及加载相关联表的数据:延迟加载、贪婪加载、显示加载
- 42、C#:EF框架的:导航属性,加载记录追踪方式(MergeOption),添加内存内容到新上下文(Attach)
- EF实体框架-从数据库更新模型 一部分表的外键(导航属性)无法显示
- EF Code First 导航属性 与外键(转载)
- EFCode First 导航属性
- Hibernate 的延迟加载【lazy】属性
- Hibernate 延迟加载,lazy属性配置。以及org.hibernate.LazyInitializationException
- 库的三种加载方法 显示加载 隐示加载 延迟加载
- 用src属性动态替换图片;图片预加载---鼠标事件实现图片翻转效果;随机显示图片和onClick事件
- ajax 延迟显示加载中提示
- EF的状态跟踪选项与导航属性
- 转:zTree高级入门:如何通过扩展节点的属性来达到是否显示节点的删除编辑等图标(按钮)
- 学习EF之贪婪加载和延迟加载(1)
- EFCode First 导航属性