【问题标题】:Entity Framework Many to Many relationship to same entity type but with different relationship type实体框架多对多关系到相同的实体类型但具有不同的关系类型
【发布时间】:2014-03-28 11:58:53
【问题描述】:

使用 Entity Framework 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; }

}

我希望它表示的是,例如,我可能将 Siblings 作为关系类型,将 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

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

谢谢

【问题讨论】:

    标签: c# entity-framework model entity relationship


    【解决方案1】:

    Relationship_ID 源自 Relationship.RelatedPersons 集合。我认为这里有一个 collection 是不正确的,而应该是单个 reference 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 的反向导航属性。如果没有该属性,您将在 Relationship 表中获得 三个 外键,这些外键引用了 Person 表。

    您可能还需要为其中一个关系禁用级联删除,以避免出现从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);
    

    【讨论】:

    • 完全正确,我只是把关系搞错了,最后按照你的建议找到了解决方案。唯一的区别是为了完整性,我添加了第二个 ICollection 虚拟属性,其 InverseProperty 为“RelatedPerson”。另外,我没有走 Fluent API 路线,我只是将 RelatedId 和 RelatedPersonId 设置为可为空(int?),这解决了级联问题。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-24
    • 1970-01-01
    • 2019-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多