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).

entityframework学习笔记--008-实体数据建模基础之继承关系映射TPH

图8-1

2.右键你的项目,添加上图中的poco实体。如下:

[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())
.Map<HourlyEmployee>(m => m.Requires("EmployeeType").HasValue());//如果去掉这两个map,会发现程序也能正常运行,并且在Employee表中生成了一个额外属性“Discriminator”
}
}

4.测试代码:

 using (var context = new EF6RecipesContext())
{
var fte = new FullTimeEmployee
{
FirstName = "Jane",
LastName = "Doe",
Salary = 71500M
};
context.Employees.Add(fte);
fte = new FullTimeEmployee
{
FirstName = "John",
LastName = "Smith",
Salary = 62500M
};
context.Employees.Add(fte);
var hourly = new HourlyEmployee
{
FirstName = "Tom",
LastName = "Jones",
Wage = 8.75M
};
context.Employees.Add(hourly);
context.SaveChanges();
}
using (var context = new EF6RecipesContext())
{
Console.WriteLine("--- All Employees ---");
foreach (var emp in context.Employees)
{
bool fullTime = emp is HourlyEmployee ? false : true;
Console.WriteLine("{0} {1} ({2})", emp.FirstName, emp.LastName,
fullTime ? "Full Time" : "Hourly");
}
Console.WriteLine("--- Full Time ---");
foreach (var fte in context.Employees.OfType<FullTimeEmployee>())
{
Console.WriteLine("{0} {1}", fte.FirstName, fte.LastName);
}
Console.WriteLine("--- Hourly ---");
foreach (var hourly in context.Employees.OfType<HourlyEmployee>())
{
Console.WriteLine("{0} {1}", hourly.FirstName, hourly.LastName);
}
}

输出如下:

--- 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连接问题,并带来了好的性能。但牺牲了数据库的灵活性。
上一篇:zabbix监控mysql性能


下一篇:AE 将地图导出为图片的两种方法