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

本文关键字:实体 类型 关系 框架 关系到 | 更新日期: 2023-09-27 17:54:21

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

public class Person
{
    public int ID { get; set; }
    public string Name { get; set; }
    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; }
    public virtual ICollection<Person> RelatedPersons { get; set; }
}

我想要它表示的是,例如,我可能将sibling作为关系类型,UnclesAndAunts作为另一种关系类型,并且不需要知道这些类型的关系是谁,因为他们可能不在数据库中。

使用Code First,这将生成一个表模式…

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

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.

这样做的问题是,由于Person表中的Relationship_ID这意味着Person表将具有重复数据而我希望Relationship表具有重复数据,例如

Relationship...
ID   RelationshipType PersonID    Person_ID
---------------------------------------------
1    Sibling           1           2
2    Sibling           1           3
3    UnclesAndAunts    1           4

谁能告诉我我应该如何用模型类来表示这个,我假设有一些属性或其他我需要包括的。

谢谢

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

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; }
}

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

您可能还需要禁用其中一个关系的级联删除,以避免从PersonRelationship的禁止多个级联删除路径的异常。这可以用Fluent API完成:

modelBuilder.Entity<Relationship>()
    .HasRequired(r => r.RelatedPerson)
    .WithMany()
    .HasForeignKey(r => r.RelatedPersonID)
    .WillCascadeOnDelete(false);

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

modelBuilder.Entity<Relationship>()
    .HasRequired(r => r.Person)
    .WithMany(p => p.Relationships)
    .HasForeignKey(r => r.PersonID);