EF實體框架處理實體之間關聯關系與EF延遲機制(下)


       在數據庫中,表與表之間可能存在多種聯系,比如,一對多,多對多的關系。當我們使用邏輯外鍵在數據庫建立兩張表之間的關系的時候,我們使用EF實體框架  

必然也會將這種關系映射到我們的實體關系中來。所以,在我們做項目的時候,很多情況下我們都使用邏輯外鍵建立兩張表之間的關系,從而避免刪除等操作帶來的種  

種問題。  

      那么,我們的EF實體框架是怎么解決這種關聯關系呢?假如給我們兩張表,一張是用戶表,另外一張是訂單表。用戶表與訂單表是一對多的關系,我們來仿照EF  

代碼簡單的寫一個自己的框架(CodeOnly)  

      第一步:建兩個類UserInfo和Order類  

      下面這時UserInfo類:  

 1 namespace codeOnly  2 {  3 public class UserInfo  4  {  5  [Key]  6 public int Id { get; set; }  7 public string UName { get; set; }  8 //這里顯示了一對多的關系,一個用戶可以有多個Order表  9 public ICollection<Order> Order { get; set; } 10  } 11 }

   下面這是Order類  

namespace codeOnly { public class Order { [Key] public int Id { get; set; } public string Content { get; set; } //一個Order對應一個User public UserInfo User { get; set; } } }

  這樣便解決了一對多的關系,多對多的實現也是如此,那么我們再來看看它的上下文的實現過程吧  

 1 namespace codeOnly  2 {  3 public class DbContentDemo:DbContext  4  {  5 //實現了.Net與數據庫的連接  6 public DbContentDemo()  7 : base("name=Demo")  8  {  9 10  } 11 public DbSet<UserInfo> UserInfo { get; set; } 12 public DbSet<Order> Order { get; set; } 13  } 14 }

         看到這里,我們是不是就想起了HttpContext這個類呢,簡直是具有異曲同工之處呢。前邊也已經介紹了上下文的作用,這里就不再多說了,主要介紹一下其  

中“name=Demo”的作用。在App.config下:Demo就是與數據庫進行連接的字符串。所以它在內部實現了與數據庫進行連接的操作。下面這段代碼就可以實現在數  

據庫中創建與我們的實體一一對應的表格了。  

 1 namespace codeOnly  2 {  3 class Program  4  {  5 public static void Main(string[] args)  6  {  7 DbContentDemo dbcontext = new DbContentDemo();  8 //初始化數據庫  9 dbcontext.Database.CreateIfNotExists();//如果數據庫不存在則自動創建 10 UserInfo user = new UserInfo(); 11 user.Id = 5; 12 user.UName = "大家好"; 13  dbcontext.SaveChanges(); 14  Console.ReadKey(); 15  } 16 }

         上面這些代碼頗為簡單,相信大家都能看明白EF實體框架內部的處理過程是怎樣的了(這是ModelFirst的情況),那么在DbFirst的情況下處理一對多多對多的關系  

我們也簡單的用一段小代碼來詮釋吧。  

 1 namespace ModelFirstaaaa  2 {  3 class Program  4  {  5 static void Main(string[] args)  6  {  7 //一對多的關系  8 Model1Container dbContext=new Model1Container();  9 UserInfo user=new UserInfo(); 10 user.ID = 5; 11 user.IsDel = "false"; 12 user.Phone = "13363605745"; 13 user.SubTime=DateTime.Now; 14 user.UName = "大家好"; 15  dbContext.UserInfo集.AddObject(user); 16 17 Order order=new Order(); 18 order.ID = 5; 19 order.Content = "你哈"; 20 order.UserInfo = user; 21 22  dbContext.SaveChanges(); 23 Console.WriteLine("執行成功"); 24  Console.ReadKey(); 25 26 //多對多的關系 27 28 #region 多對多的關系 29 Model1Container dbContext = new Model1Container(); 30 UserInfo user = new UserInfo(); 31 user.ID = 6; 32 user.IsDel = "false"; 33 user.Phone = "13363605745"; 34 user.SubTime = DateTime.Now; 35 user.UName = "me"; 36  dbContext.UserInfo集.AddObject(user); 37 38 Order order = new Order(); 39 order.Content = "你好"; 40 order.ID = 7; 41  dbContext.Order.AddObject(order); 42 43  order.UserInfo.Add(user); 44  dbContext.SaveChanges(); 45 Console.WriteLine("ok"); 46 #endregion 47  } 48  } 49 }

              另外,EF還有一個很優美的特定,那就是延遲加載的特性。EF       中第一個延遲加載機制:當我們用到的時候才會去加載數據。每次使用的時候都會全新為我們加       

載數據。使用多少次便查詢多少次      。當我們使用Linq表達式寫一個查詢語句的時候,返回的結果基本上都是一個       IQuerable       類型集合,數據庫的sql執行的順序一般為from,       

      where,select......而我們EF實體框架將程序編譯成sql腳本的時候 先把執行的順序根據算法生成樹的形式(編譯原理),根節點是       from,       先中間,后左邊,然后最右邊。       

有可能繼續      而我們       C#       提供的       Expression       類型就為我們提供了樹的結構。我們寫的       Linq       表達式最終只不過是將       Linq       生成了表達式放到了       Expression       表達式類型中去了。放到了       

IQueryable       內部中去了。我們用到的       IQueryable       接口的集合的時候,       IQuerable       集合內部的       Provider       屬性會解析       Expression,       然后生成相應的sql語句去做相應查詢並加載數據。       

     

1 var data = dbContext.ClassInfo.Where(c => c.ClassName.Contains("計算機")); 2 foreach (var classinfor in data) 3  { 4 Console.WriteLine(classinfor.ClassId+classinfor.ClassName); 5 }

   

2.第二種延遲加載機制:  

     導航屬性的延遲加載機制:如果實體是查詢出來的,那么通過導航屬性去訪問其它有關聯的實體的時候       EF       會自動幫我們去查詢關聯表的數據。不管有沒有       ToList,       

導航屬性      有個需求:緩存。       IQueryable       是一個非常特殊的接口,數據並不存放在本地,只有用到的時候通過       Provinder       去解析加載數據       (       它本身是不存儲數據的       )       。而我們       

List       ,       Array(實現了IEnumrable接口,可以對數組進行遍歷)       都是一個本地集合      。Var  users=(from u in dbHmEntities select u).ToList();當查詢成功的       時候就相       

當於將數據庫中的內容立刻加載到內存中,這時候使用       foreach       遍歷集合的時候就不會去執行       sql       腳本了。       FirstOrDefault       也是立即去查詢。                 

1 //IQueryable:是非常特殊的接口,數據並不存放在本地,只有用到的時候去解析Exp加載數據。 2 var data2 = dbContext.ClassInfo.Where(c => c.ClassName.Contains("計算機")).ToList(); 3 foreach (var classinfo in data2) 4  { 5 Console.WriteLine(classinfo.ClassName+classinfo.ClassId); 6 }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM