第六节: EF高级属性(二) 之延迟加载、立即加载、显示加载(含导航属性)
一. 簡介
? 上一個(gè)章節(jié)中,也介紹了立即加載和延遲加載,但上一個(gè)章節(jié)是針對(duì)單表而言的,不含外鍵,立即也好,延遲也好,都是指單表中的數(shù)據(jù)。但本章節(jié)重點(diǎn)介紹的三種加載方式均是針對(duì)含(導(dǎo)航屬性、外鍵)的情況下,查詢主表,從表中的數(shù)據(jù)加載情況。
下面準(zhǔn)備兩張表:Student和StudentAddress兩張表,一對(duì)一 or 零 的關(guān)系,實(shí)體結(jié)構(gòu)如下,通過CodeFirst來反向生成數(shù)據(jù)庫。
1 /// <summary>2 /// 學(xué)生表(一個(gè)學(xué)生只能有一個(gè)地址或沒有地址)3 /// </summary>4 public class Student5 {6 public Student()7 {8 9 } 10 public string studentId { get; set; } 11 12 public string studentName { get; set; } 13 14 15 public virtual StudentAddress StudentAddress { get; set; } 16 } 1 /// <summary>2 /// 學(xué)生地址表(一個(gè)地址只能對(duì)應(yīng)一個(gè)學(xué)生)3 /// </summary>4 public class StudentAddress5 {6 public StudentAddress()7 {8 9 } 10 11 [ForeignKey("stu")] 12 //特別注意這個(gè)地方,stu對(duì)應(yīng)下面的 Student stu; 13 //另外特別注意:studentAddressId,符合默認(rèn)的Id生成規(guī)則,自動(dòng)映射成主鍵,否則需要加【key】特性 14 public string studentAddressId { get; set; } 15 16 public string addressName { get; set; } 17 18 public virtual Student stu { get; set; } 19 }二. Lazy Loading
?1. 又名:延遲加載、懶加載
?2. 需要滿足的條件:
? ①:poco類是public且不能為sealed
? ②:導(dǎo)航屬性需要標(biāo)記為Virtual
? 滿足以上兩個(gè)條件,EF6默認(rèn)就為延遲加載的模式。(默認(rèn):db.Configuration.LazyLoadingEnabled = true; )
3. 含義:每次調(diào)用子實(shí)體(外鍵所在的實(shí)體)的時(shí)候,才去查詢數(shù)據(jù)庫. 主表數(shù)據(jù)加載的時(shí)候,不去查詢外鍵所在的從表。
4. 關(guān)閉延遲加載的辦法: db.Configuration.LazyLoadingEnabled = false;
特別注意:關(guān)閉延遲加載后,查詢主表數(shù)據(jù)時(shí)候,主表的中從表實(shí)體為null.
1. 延遲加載代碼測(cè)試
1 using (dbContext1 db = new dbContext1())2 {3 Console.WriteLine("--------------------------- 01-延遲加載 -----------------------------");4 db.Database.Log = Console.WriteLine;5 6 //EF默認(rèn)就是延遲加載,默認(rèn)下面的語句就是true,所以下面語句注釋沒有任何影響7 //db.Configuration.LazyLoadingEnabled = true;8 9 var list = db.Student.ToList(); //此處加載的數(shù)據(jù),根據(jù)監(jiān)測(cè)得出結(jié)論,沒有對(duì)從表進(jìn)行任何查詢操作 10 foreach (var stu in list) 11 { 12 Console.WriteLine("學(xué)生編號(hào):{0},學(xué)生姓名:{1}", stu.studentId, stu.studentName); 13 14 //下面調(diào)用導(dǎo)航屬性(一對(duì)一的關(guān)系) 每次調(diào)用時(shí),都要去查詢數(shù)據(jù)庫(查詢從表) 15 var stuAddress = stu.StudentAddress; 16 Console.WriteLine("地址編號(hào):{0},地址名稱:{1}", stuAddress.studentAddressId, stu.studentName); 17 } 18 }2. 關(guān)閉延遲加載
1 using (dbContext1 db = new dbContext1())2 {3 try4 {5 Console.WriteLine("--------------------------- 02-關(guān)閉延遲加載 -----------------------------");6 db.Database.Log = Console.WriteLine;7 8 //下面的語句為關(guān)閉延遲加載9 db.Configuration.LazyLoadingEnabled = false; 10 11 var list = db.Student.ToList(); //關(guān)閉延遲加載后,此處從表實(shí)體StudentAddress為null,后面不會(huì)再次查詢了 12 foreach (var stu in list) 13 { 14 Console.WriteLine("學(xué)生編號(hào):{0},學(xué)生姓名:{1}", stu.studentId, stu.studentName); 15 16 //StudentAddress為null,不會(huì)再次查詢數(shù)據(jù)庫,所以此處報(bào)錯(cuò) 17 var stuAddress = stu.StudentAddress; 18 Console.WriteLine("地址編號(hào):{0},地址名稱:{1}", stuAddress.studentAddressId, stu.studentName); 19 } 20 } 21 catch (Exception ex) 22 { 23 Console.WriteLine(ex.Message); 24 } 25 }三. Eager Loading
?1. 又名:立即加載、貪婪加載、預(yù)加載
?2. 使用步驟:
? ①:先關(guān)閉延遲加載:db.Configuration.LazyLoadingEnabled = false;
?②:查詢主表的同時(shí)通過Include把從表數(shù)據(jù)也查詢出來:
?3. 含義:由于查詢主表的時(shí)候通過Include已經(jīng)一次性將數(shù)據(jù)查詢了出來,所以在調(diào)用從表數(shù)據(jù)的時(shí)候,均從緩存中讀取,無須查詢數(shù)據(jù)庫
代碼測(cè)試
1 using (dbContext1 db = new dbContext1())2 {3 Console.WriteLine("--------------------------- 03-立即加載 -----------------------------");4 db.Database.Log = Console.WriteLine;5 6 //1.關(guān)閉延遲加載7 db.Configuration.LazyLoadingEnabled = false;8 9 //2. 獲取主表數(shù)據(jù)的同時(shí),通過Include將從表中的數(shù)據(jù)也全部加載出來 10 var list = db.Student.Include("StudentAddress").ToList(); 11 foreach (var stu in list) 12 { 13 Console.WriteLine("學(xué)生編號(hào):{0},學(xué)生姓名:{1}", stu.studentId, stu.studentName); 14 15 //這里獲取從表中的數(shù)據(jù),均是從緩存中獲取,無需查詢數(shù)據(jù)庫 16 var stuAddress = stu.StudentAddress; 17 Console.WriteLine("地址編號(hào):{0},地址名稱:{1}", stuAddress.studentAddressId, stu.studentName); 18 } 19 20 }四. Explicit Loading
?1. 又名:顯示加載
?2. 背景:關(guān)閉延遲加載后,單純查詢主表的數(shù)據(jù),后面又想再次查詢從表,這個(gè)時(shí)候就需要用到顯示加載了.
?3. 前提:
? ①:關(guān)閉了延遲加載:db.Configuration.LazyLoadingEnabled = false;
? ②:單純查詢了主表,沒有使用Include函數(shù)關(guān)聯(lián)查詢從表.
?4. 使用步驟:
? ①:單個(gè)實(shí)體用:Reference
? ②:集合用:Collection
? ③:最后需要Load一下
?5. 含義:關(guān)閉了延遲加載,單純查詢了主表數(shù)據(jù),這個(gè)時(shí)候需要重新查詢從表數(shù)據(jù),就要用到顯式加載了
代碼測(cè)試
1 using (dbContext1 db = new dbContext1())2 {3 Console.WriteLine("--------------------------- 04-顯式加載 -----------------------------");4 db.Database.Log = Console.WriteLine;5 6 //1.關(guān)閉延遲加載7 db.Configuration.LazyLoadingEnabled = false;8 9 //2.此處加載的數(shù)據(jù),不含從表中的數(shù)據(jù) 10 var list = db.Student.ToList(); 11 foreach (var stu in list) 12 { 13 Console.WriteLine("學(xué)生編號(hào):{0},學(xué)生姓名:{1}", stu.studentId, stu.studentName); 14 15 //3.下面的這句話,可以開啟重新查詢一次數(shù)據(jù)庫 16 //3.1 單個(gè)屬性的情況用Refercence 17 db.Entry<Student>(stu).Reference(c => c.StudentAddress).Load(); 18 //3.2 集合的情況用Collection 19 //db.Entry<Student>(stu).Collection(c => c.StudentAddress).Load(); 20 21 //下面調(diào)用導(dǎo)航屬性(一對(duì)一的關(guān)系) 每次調(diào)用時(shí),都要去查詢數(shù)據(jù)庫 22 var stuAddress = stu.StudentAddress; 23 Console.WriteLine("地址編號(hào):{0},地址名稱:{1}", stuAddress.studentAddressId, stu.studentName); 24 } 25 26 }總結(jié)
以上是生活随笔為你收集整理的第六节: EF高级属性(二) 之延迟加载、立即加载、显示加载(含导航属性)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 茅台酒、冰淇淋全都卖:“i茅台”用户近1
- 下一篇: UWP开发入门教程备忘