1.讓咱們假設你有如圖8-1中的表,Employee表包含hourly employees 和salaried employees的行。列EmployeeType做爲鑑別列,鑑別這兩種員工類型的行。 當EmployeType爲1時,這一行表明一個專職員工(salaried or full-time employee),當值爲2時,這一行代碼一個鐘點工(hourly employee).sql
圖8-1數據庫
2.右鍵你的項目,添加上圖中的poco實體。以下:ide
[Table("Employee", Schema = "example8")] public abstract class Employee { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int EmployeeId { get; protected set; } public string FirstName { get; set; } public string LastName { get; set; } }
public class FullTimeEmployee : Employee { public decimal? Salary { get; set; } }
public class HourlyEmployee : Employee { public decimal? Wage { get; set; } }
3.建立一個繼承自DbContext的上下文對象EF6RecipesContext;性能
public class EF6RecipesContext : DbContext { public DbSet<Employee> Employees { get; set; } public EF6RecipesContext() : base("name=EF6CodeFirstRecipesContext") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity<Employee>() .Map<FullTimeEmployee>(m => m.Requires("EmployeeType").HasValue(1)) .Map<HourlyEmployee>(m => m.Requires("EmployeeType").HasValue(2));//若是去掉這兩個map,會發現程序也能正常運行,而且在Employee表中生成了一個額外屬性「Discriminator」 } }
4.測試代碼:測試
1 using (var context = new EF6RecipesContext()) 2 { 3 var fte = new FullTimeEmployee 4 { 5 FirstName = "Jane", 6 LastName = "Doe", 7 Salary = 71500M 8 }; 9 context.Employees.Add(fte); 10 fte = new FullTimeEmployee 11 { 12 FirstName = "John", 13 LastName = "Smith", 14 Salary = 62500M 15 }; 16 context.Employees.Add(fte); 17 var hourly = new HourlyEmployee 18 { 19 FirstName = "Tom", 20 LastName = "Jones", 21 Wage = 8.75M 22 }; 23 context.Employees.Add(hourly); 24 context.SaveChanges(); 25 } 26 using (var context = new EF6RecipesContext()) 27 { 28 Console.WriteLine("--- All Employees ---"); 29 foreach (var emp in context.Employees) 30 { 31 bool fullTime = emp is HourlyEmployee ? false : true; 32 Console.WriteLine("{0} {1} ({2})", emp.FirstName, emp.LastName, 33 fullTime ? "Full Time" : "Hourly"); 34 } 35 Console.WriteLine("--- Full Time ---"); 36 foreach (var fte in context.Employees.OfType<FullTimeEmployee>()) 37 { 38 Console.WriteLine("{0} {1}", fte.FirstName, fte.LastName); 39 } 40 Console.WriteLine("--- Hourly ---"); 41 foreach (var hourly in context.Employees.OfType<HourlyEmployee>()) 42 { 43 Console.WriteLine("{0} {1}", hourly.FirstName, hourly.LastName); 44 } 45 }
輸出以下:ui
--- All Employees ---Jane Doe (Full Time) John Smith (Full Time) Tom Jones (Hourly) --- Full Time ---Jane Doe John Smith --- Hourly ---Tom Jones
5.注意看步驟3中的註釋,若是註釋掉「OnModelCreating」中的內容,查詢Employee生成的sql以下:
SELECT [Extent1].[Discriminator] AS [Discriminator], [Extent1].[EmployeeId] AS [EmployeeId], [Extent1].[FirstName] AS [FirstName], [Extent1].[LastName] AS [LastName], [Extent1].[Salary] AS [Salary], [Extent1].[Wage] AS [Wage] FROM [example8].[Employee] AS [Extent1] WHERE [Extent1].[Discriminator] IN (N'FullTimeEmployee',N'HourlyEmployee')
其實「TPT」與「TPH」的關係能夠簡單的理解成,是否子類與父類映射到同一張表。「TPT」相對靈活,單查詢時使用了join,性能天然而然會有稍微影響;「TPH」 它將整個繼承類型存儲在一張單獨的表中,他解決了TPT中的join鏈接問題,並帶來了好的性能。但犧牲了數據庫的靈活性。