您好,登錄后才能下訂單哦!
問題描述:
假設有一些表用于保存公共表的額外信息,現在想使用TPT繼承對其建模。
解決方案:
假定現在有2個表關聯到一個公共表,如下圖所示:
Business表和Retail表及eCommerce表間都是一個1對零個或1個的關系,其中Business表是1端。關鍵的特點是Retail表和eCommerce表擴展了Business表中business的信息。
Business表包含一些任何business都有的公共屬性,Retail表和eCommerce表都同它緊密相連。為了建模一個TPT繼承,也就是說Retail實體類型和eCommerce實體類型都繼承于Business基實體類型,需要實現以下步驟:
1、生成一個派生自DbContext類的類,需要引入System.Data.Entity名稱空間,添加默認構造函數,并調用父類的構造函數base("name=connectionStringName")。connectionStringName是EF框架的連接字符串名稱,在配置文件中可以找到,沒有的話需要手動添加或使用EDM向導的代碼優先方式創建。并重寫父類的OnModelCreating方法。
2、生成一個Business POCO 實體類型。
[Table("Business",Schema ="Chapter2")] public class Business { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int BusinessId { get; set; } public string Name { get; set; } public string LicenseNumber { get; set; } }
3、生成一個eCommerce POCO 實體類型和Retail POCO 實體類型,它們都繼承于Business POCO實體類型。
[Table("eCommerce",Schema ="Chapter2")] public class eCommerce:Business { public string URL { get; set; } } [Table("Retail",Schema ="Chapter2")] public class Retail : Business { public string Address { get; set; } public string City { get; set; } public string State { get; set; } public string ZIPCode { get; set; } }
4、在DbContext子類中添加一個DbSet<Business>自動屬性。
原理:
Retail表和eCommerce表是同Business表的1:0..1關系的0..1端。這意味著一個business實體可以沒有任何額外的信息,也可以有額外的Retail信息或eCommerce信息。在OOP術語中,描述為一個基類型Business和2個派生類型Retail和eCommerce。
因為這是一個1:0..1的關系,所以在Retail表和eCommerce表中不存在這樣的記錄,它們在Business表中不存在相關的記錄。在面向對象的術語中描述為,派生類的實例包含有基類的屬性。派生類擴展基類屬性的概念是繼承的關鍵特性之一。在TPT繼承中,每一個派生類都表示為一個單獨的表。
using (var context = new EF6Recipes8Context()) { var business = new Business { Name = "Corner Dry Cleaning", LicenseNumber = "100x1" }; context.Businesses.Add(business); var retail = new Retail { Name = "Shop and Save", LicenseNumber = "200C", Address = "101 Main", City = "AnyTown", State = "TX", ZIPCode = "76106" }; context.Businesses.Add(retail); var web = new eCommerce { Name = "BuyNow.com", LicenseNumber = "300AB", URL = "www.buynow.com" }; context.Businesses.Add(web); context.SaveChanges(); } using (var context = new EF6Recipes8Context()) { Console.WriteLine("\n--- All Business ---"); foreach (var b in context.Businesses) { Console.WriteLine("{0} (#{1})", b.Name, b.LicenseNumber); } Console.WriteLine("\n---Retail Business ---"); foreach (var r in context.Businesses.OfType<Retail>()) { Console.WriteLine("{0} (#{1}", r.Name, r.LicenseNumber); Console.WriteLine("{0}", r.Address); Console.WriteLine("{0}, {1} {2}", r.City, r.State, r.ZIPCode); } Console.WriteLine("\n--- eCommerce Business ---"); foreach (var e in context.Businesses.OfType<eCommerce>()) { Console.WriteLine("{0} (#{1})", e.Name, e.LicenseNumber); Console.WriteLine("Online address is: {0}", e.URL); } }
上面的代碼生成和實例化Business實體類型和2個派生類型,并使用context中的Business實體集合的Add()方法將其添加到context中。
在查詢部分,為了訪問所有的business實例,我們迭代整個business實體集合;為了獲取派生類型,我們調用OfType方法過濾Business實體集合。
TPT是EF支持的3種繼承模式中的一個。另外2個是TPH(Table per Hierarchy)和TPCT(Table per Concrete Type)。
TPT繼承提供了很大的數據庫靈活性,我們能夠容易的添加表作為一個派生類型,并按照它們自己的方式添加到模型中。然而,每一個派生類型涉及額外的連接,這將導致性能下降。在實際的應用中,使用TPT時,我們已經看到顯著的性能問題當一些派生類被建模時。
而TPH存儲整個繼承在單個表,它消除了TPT的連接,因此提供更好的性能,但更低的靈活性。
TPCT被EF運行時支持,而不是設計時。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。