实体框架与相同实体类型但具有不同关系类型的多对多关系

Hoo*_*ots 2 c# entity entity-framework model relationship

使用实体框架 6,我有一个 Person 类...

public class Person
{
    public int ID { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Relationship> Relationships { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

和一个关系类

public class Relationship
{
    public int ID { get; set; }
    public RelationshipType DependencyType { get; set; }

    [ForeignKey("Person")]
    public int PersonID { get; set; }
    public virtual Person Person { get; set; }

    public virtual ICollection<Person> RelatedPersons { get; set; }

}
Run Code Online (Sandbox Code Playgroud)

我希望这代表的是,例如,我可能将兄弟姐妹作为一种关系类型,将叔叔和阿姨作为另一种关系类型,并持有这些类型的关系,而无需知道父母是谁,因为他们可能不在数据库中。

使用 Code First,这会生成一个表模式...

CREATE TABLE [dbo].[Person](
[ID] [int] IDENTITY(1,1) NOT NULL,
 [Name] [nvarchar](max) NULL,
[Relationship_ID] [int] NULL)
Run Code Online (Sandbox Code Playgroud)

CREATE TABLE [dbo].[Relationship](
    [ID] [int] IDENTITY(1,1) NOT NULL,
[RelationshipType] [int] NOT NULL,
[PersonID] [int] NOT NULL,
[Person_ID] [int] NULL)

PersonID is the main Person of this relationship.
Person_ID is the Person to whom the main person is related to.
I would see the Relationship table containing repeated PersonID data.
Run Code Online (Sandbox Code Playgroud)

问题在于,由于 Person 表中的 Relationship_ID 是说 Person 表将具有重复数据,而我希望关系表具有重复数据,例如

Relationship...

ID   RelationshipType PersonID    Person_ID
---------------------------------------------
1    Sibling           1           2
2    Sibling           1           3
3    UnclesAndAunts    1           4
Run Code Online (Sandbox Code Playgroud)

有人可以告诉我应该如何用模型类来表示这一点,我假设我需要包含一些属性或其他属性。

谢谢

Sla*_*uma 5

Relationship_ID从茎Relationship.RelatedPersons集合。我认为在这里有一个集合是不正确的,它应该是一个单一的引用 RelatedPerson(单数),因为一个Relationship实体描述了两个人之间的关系,而不是一个人和其他人的集合之间的关系。所以,我建议像这样改变模型:

public class Person
{
    public int ID { get; set; }
    public string Name { get; set; }

    [InverseProperty("Person")]
    public virtual ICollection<Relationship> Relationships { get; set; }
}

public class Relationship
{
    public int ID { get; set; }
    public RelationshipType DependencyType { get; set; }

    [ForeignKey("Person")]
    public int PersonID { get; set; }
    public virtual Person Person { get; set; }

    [ForeignKey("RelatedPerson")]
    public int RelatedPersonID { get; set; }
    public virtual Person RelatedPerson { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

[InverseProperty]属性在这里很重要,它告诉 EF 这Relationship.Person是 的逆导航属性Person.Relationships。如果没有该属性,您将在表中获得三个引用该Relationship表的外键Person

您可能还需要禁用其中一个关系的级联删除,以避免出现关于从Person到 的禁止多个级联删除路径的异常Relationship。可以使用 Fluent API 来完成:

modelBuilder.Entity<Relationship>()
    .HasRequired(r => r.RelatedPerson)
    .WithMany()
    .HasForeignKey(r => r.RelatedPersonID)
    .WillCascadeOnDelete(false);
Run Code Online (Sandbox Code Playgroud)

一旦你有了它,你也可以添加与 Fluent API 的第二个关系,这将允许你从模型中删除所有属性,因为它们是多余的,然后:

modelBuilder.Entity<Relationship>()
    .HasRequired(r => r.Person)
    .WithMany(p => p.Relationships)
    .HasForeignKey(r => r.PersonID);
Run Code Online (Sandbox Code Playgroud)