本章節講解EF裏的繼承映射關係,分爲TPH、TPT、TPC。具體:html
1.TPH:Table Per Hierarchy數據庫
這是EF的默認的繼承映射關係:一張表存放基類和子類的全部列,自動生成的discriminator列用來區分基類和子類的數據。新建一個度假村Resort實體類試試:api
/// <summary> /// 度假村類 /// </summary> public class Resort : Lodging //這裏繼承了Lodging類 { public string Entertainment { get; set; } //娛樂 public string Activities { get; set; } //活動 }
以前的住宿類Lodging裏有個屬性IsResort表示是否度假勝地,如今能夠註釋掉了,有新的類Resort來繼承Lodging表示是不是度假勝地了,跑下程序最終會生成一張表:app
並無生成Resorts表,而是把Resrot實體類裏的屬性生成到了Lodgings表裏。多了一列discriminator,這個是默認的,用來表示數據來自哪一個類,繼續添加一個插入Lodging表數據的方法:工具
private static void InsertLodging() { var lodging = new CodeFirst.Model.Lodging { Name = "Rainy Day Motel", Destination = new CodeFirst.Model.Destination { Name = "Seattle, Washington", Country = "USA" } }; using (var context = new CodeFirst.DataAccess.BreakAwayContext()) { context.Lodgings.Add(lodging); context.SaveChanges(); } }
再添加一個插入Resort表數據的方法:性能
private static void InsertResort() { var resort = new CodeFirst.Model.Resort { Name = "Top Notch Resort and Spa", MilesFromNearestAirport = 30, Activities = "Spa, Hiking, Skiing, Ballooning", Destination = new CodeFirst.Model.Destination { Name = "Stowe, Vermont", Country = "USA" } }; using (var context = new CodeFirst.DataAccess.BreakAwayContext()) { context.Lodgings.Add(resort); context.SaveChanges(); } }
在Main方法裏調用兩個插入方法,可獲得以下數據:測試
兩個插入的數據都到了一張表裏。Discriminator列表示數據來自哪一列。固然是能夠配置的,這裏就必須使用Fluent API配置了,Data Annotation表示無能爲力,到LodgingMap裏進行配置:ui
this.Map<CodeFirst.Model.Lodging>(l => { l.Requires("From").HasValue("Standard"); }); this.Map<CodeFirst.Model.Resort>(l => { l.Requires("From").HasValue("Resort"); });
生成了咱們指定的From列,數據Standard、Resort分別表示來自Lodging和Resrot表,形象點就是1號酒店是普通酒店,2號就是是度假勝地的酒店:this
固然,這裏甚至能夠把HasValue方法裏的參數設置成True和False,用布爾類型的數據區分普通酒店和度假勝地的酒店更形象,園友lk8167給了一個更形象的普通售貨員和銷售經理的例子rest
2.TPT:Table Per Type
父類和子類在不一樣的表裏。使用Data Annotation配置TPT:
按 Ctrl+C 複製代碼
按 Ctrl+C 複製代碼
或者使用Fluent API配置:
按 Ctrl+C 複製代碼
按 Ctrl+C 複製代碼
注意:上面配置TPH的Fluetn API須要註釋掉在跑程序,那是測試TPH的配置。同時釋放這句的註釋:context.Database.Initialize(true);,這裏沒修改實體,可是也須要從新生成數據庫。最終數據庫是這樣的:
父類和子類實體都有一張表,子表經過主鍵LodgingId找到父表:
3.TPC:Table Per Concrete Type
爲每一個子類創建一個表,每一個與子類對應的表中包含基類的屬性對應的列和子類特有屬性對應的列。一樣以前配置TPT的Fluent API須要先註釋掉,而後咱們經過Fluent API配置下TPC,TPC也沒法用Data Annotation配置:
按 Ctrl+C 複製代碼
按 Ctrl+C 複製代碼
生成的數據庫:
可見,子類Resorts類也有了基類的全部屬性。
注意:爲了方便測試生成TPC,我註釋了全部Lodging表的導航屬性,主要是和Destination的一對多關係、Destination類也須要註釋掉Lodging屬性和Fluent API關係配置,不然程序跑起來會報DataException錯:
An exception occurred while initializing the database. See the InnerException for details.
你們下載demo使用的時候也須要先註釋掉Lodging類的導航屬性。固然不註釋想保留也能夠,必須設置外鍵爲可空類型,具體請參考Programming Entity Framework: Code First 第五章 Avoiding Mapping Exceptions with TPC
講了這幾種方式配置繼承映射,實際項目中應該用哪一個呢?
本系列文章結束,主要講解了EF裏如何使用Code First的方式配置數據庫,基本上都是手寫的配置,其實你們可能已經想到會有工具能夠自動配置這些關係了,對了,就是EF Power Tools。這個工具至關智能,能夠直接配置出全部的關係。不過我的仍是建議關係很少的話本身手寫Fluent API來配置。
另外,前面配置了那麼長時間的一對多、多對多等各類關係。配置好了如何用EF對這些數據進行增查改查呢?後續還會有系列文章講解EF是如何操做數據庫的,請保持關注。
EF Code First 系列文章導航: