这些天来,我一直在研究实体框架6的继承(MVC,VisualStudio 2015,代码优先)。从不同的方面尝试,我发现需要生成一个标识子类的PrimaryKey,与从父类继承的primaryKey / ForeignKey分开。
我要发展的想法是这样的:
public class Person
{
[Key]
public int PersonId { get; set; }
}
public class Student : Person
{
[Key]
public int StudentId { get; set; }
}
我一直在为其他尝试过此方法的人服务,但我什么也没找到。我不确定是否可以这样做,所以如果有人可以帮助我,我将非常感谢
谢谢。
最佳答案
如果您要描述Student
,并且必须描述Student.StudentId
和Student.PersonId
的含义,您能给出一个适当的描述吗?
在我看来,您要为学生提供主键的新属性的唯一原因是该属性的标识符,而不是真正有意义的含义。
在Entity Framework中为继承建模时应使用的方法取决于您最常使用的查询类型。
假设您有三种类型的人员:学生,教师和父母。考虑您最常执行的查询类型:
您最常会问有...的学生或有...的父母吗?
或者,您最常会这样对待…………的人,而…………………………的学生却很少?
(1)主要要求学生...:使用TPC
如果将继承策略建模为Table per Concrete Class (TPC),则学生,教师和家长将各自拥有自己的表。没有公用的“父母”表。学生表中有学生拥有的所有父级属性,而教师表中也有类似的所有这些父级属性。
如果您主要要求...的学生,而很少要求...的人,则使用这种继承策略是最好的。使用TPC要求...的学生……只需要一张桌子。要求人员...将始终需要对...学生,...教师,...父母的查询结果的串联
我发现这是我最常使用的继承策略。
(2)主要要求...的人:使用TPT
如果这些查询是最常用的查询,则最好在单独的表中对所有“人”数据建模,并让“学生”,“教师”和“家长”都对其“人”数据有一些引用:Table-Per-Type (TPT)
如何实施TPC
如果您根据TPC实现继承,则不会有单独的Person表。无需给人一个ID。
class Person
{
public string FirstName {get; set;}
...
}
class Student : Person
{
public int Id {get; set;}
...
}
class Teacher : Person
{
public int Id{get; set;
...
}
如果您计划从不实例化一个Person,则只有学生,老师和父母可以考虑声明Person类的摘要
顺便说一句,如果为主键属性指定默认名称
Id
,则实体框架将知道这应该是您的主键。不需要属性,也不需要流畅的API。在您的DbContext中:
class MyDbContext : DbContext
{
public DbSet<Student> Students {get; set;}
public DbSet<Teacher> Teachers {get; set;}
public DbSet<Parent> Parents {get; set;}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Student>().Map(student =>
{
student.MapInheritedProperties();
student.ToTable(nameof(MyDbContext.Students));
});
modelBuilder.Entity<Teacher>().Map(teacher =>
{
teacher.MapInheritedProperties();
teacher.ToTable(nameof(MyDbContext.Teachers));
});
// etc. for Parent
}
}
如何实施TPT
将有一个“人”表,“学生和教师”将参考“人”表。
class Person
{
public int Id {get;set;}
...
}
class Student
{
public int Id {get;set;}
// A student has Person data via foreign key:
public int PersonId {get; set;}
public Person Person {get; set;}
...
}
class Teacher
{
public int Id {get;set;}
// A Teacher has Person data via foreign key:
public int PersonId {get; set;}
public Person Person {get; set;}
...
}