C#EF6 Code First TPH - 使用注释来吸引同一实体的两个实体的导航属性

时间:2015-03-13 17:04:02

标签: c# sql-server entity-framework inheritance

我对EF6有疑问。假设我有一个如下所示的抽象基类:

[Table("Persons")]
public abstract class Person
{
    [Key]
    public int Id { get; set; }

    [Required, ForeignKey("Group")]
    public int GroupId { get; set; }

    [Required(AllowEmptyStrings = true), MaxLength(150)]
    public string FirstName { get; set; }

    [Required(AllowEmptyStrings = true), MaxLength(150)]
    public string LastName { get; set; }
}

然后有两个实体继承Person

[Table("Persons")]
public class Teacher : Person
{
    [Required]
    public int ExpirienceInYears { get; set; }
}

[Table("Persons")]
public class Student : Person
{
    [Required]
    public int Age { get; set; }
}

这对我来说一切都很好。我们有一些TPH,这就是我们获得Discriminator专栏的原因。好的,很好但我的问题是表Groups中的导航属性,实际上看起来像这样:

[Table("Groups")]
public class Group
{
    [Key]
    public int Id { get; set; }

    [Required(AllowEmptyStrings = true), MaxLength(150)]
    public string Name { get; set; }

    public virtual ICollection<Teacher> Teachers { get; set; }
    public virtual ICollection<Student> Students { get; set; }
}

似乎导航属性负责在名为Group_IdGroup_Id1的表人员中生成两列,这两列始终为空。我不需要此列,因为在此表中已有一列GroupId,其中包含Groups个点。导航属性也不起作用,所以我觉得我做错了。

表格Persons如下:

Id |  GroupId | FirstName | LastName | ExpirienceInYears | Age | Discriminator | Group_Id | Group_Id1

但我希望这张表看起来像:

Id |  GroupId | FirstName | LastName | ExpirienceInYears | Age | Discriminator

如果我删除导航属性一切正常,但我很乐意保留它们,因为它们非常方便。有什么想法吗?

1 个答案:

答案 0 :(得分:3)

问题是您正在配置两个一对多关系,一个在TeacherGroup之间,另一个在StudentGroup之间,这就是你的方式在Group_Id表格中有两个额外的FK列(Group_Id1Persons)。要实现您的目标,您需要在PersonGroup之间建立一种关系:

[Table("Persons")]
public abstract class Person
{
    [Key]
    public int Id { get; set; }
    //...
    [ForeignKey("Group")]
    public int GroupId { get; set; }

    public virtual Group Group { get; set; }
}

[Table("Groups")]
public class Group
{
    [Key]
    public int Id { get; set; }

    //...
    public virtual ICollection<Person> Persons { get; set; }    
}

然后,如果您需要与特定群体的学生一起工作,您可以这样过滤它们:

var group=db.Groups.Find(1);//search an specific group
var students=group.Persons.OfType<Student>();// get all the students of that group