Entity Framework Core Tutorial 遗产
什么是实体框架中的继承类型?
实体框架代码首先为每个具体的域类创建表。您还可以使用继承来设计域类。
- 在面向对象的编程中,我们可以包含“has a”和“is a”关系,而在基于SQL的关系模型中,我们在表之间只有“has a”关系,并且不支持类型继承。
- 那么,您如何使用关系数据库映射面向对象的域类?
回答
在Entity Framework中有三种表示继承层次结构的方法;
Entity Framework Core目前仅实现TPH模式,但考虑包含TPC和TPT,但尚未确定日期。
每个层次表(TPH)
TPH继承使用一个数据库表来维护继承层次结构中所有实体类型的数据。
- 整个类层次结构可以映射到单个表。
- 该表包含层次结构中所有类的所有属性的列。
- 由特定行表示的具体子类由类型鉴别器列的值标识。
这是一个非常简单的模型,它包含一个抽象类Person
和两个非抽象类Student
和Teacher
。 Student
和Teacher
类继承Person类。
public abstract class Person { public int Id { get; set; } public string FullName { get; set; } } public class Student : Person { public DateTime EnrollmentDate { get; set; } } public class Teacher : Person { public DateTime HireDate { get; set; } }
如果您不希望为层次结构中的一个或多个实体公开DbSet,则可以使用Fluent API确保它们包含在模型中。如果您不依赖约定,则可以使用HasBaseType显式指定基类型。
public class MyContext : DbContext { public DbSet<Person> People { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer(@"Data Source=(localdb)\ProjectsV13;Initial Catalog=MyContextDb;"); } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Teacher>().HasBaseType<Person>(); modelBuilder.Entity<Student>().HasBaseType<Person>(); } }
现在,要使用模型中的迁移创建数据库,请在程序包管理器控制台中运行以下两个命令。
PM> Add-Migration init
PM> Update-Database
正如您在数据库模式中所看到的,Code First已在一个表中添加了所有属性,并添加了一个鉴别器列来区分持久类。

TPH有一个主要问题,子类声明的属性列在数据库中可以为空。
- 例如,Code First创建了一个(DATETIME,NULL)列来映射Teacher类中的HireDate属性和Student类中的EnrollmentDate。
- 教师实例不具有EnrollmentDate属性;该行的EnrollmentDate字段必须为NULL。
- 同样,student实例不具有HireDate属性,因此该行的HireDate字段必须为NULL。
有关更多信息,请参阅继承(关系数据库)