entityframework學習筆記--008-實體數據建模基礎之繼承關係映射TPH

Table per Hierarchy Inheritance 建模

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; }
    }
Employee
public class FullTimeEmployee : Employee
    {
        public decimal? Salary { get; set; }
    }
FullTimeEmployee
public class HourlyEmployee : Employee
    {
        public decimal? Wage { get; set; }
    }
HourlyEmployee

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             }
View Code

輸出以下: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鏈接問題,並帶來了好的性能。但犧牲了數據庫的靈活性。
相關文章
相關標籤/搜索