实体框架与相同实体类型但具有不同关系类型的多对多关系 [英] Entity Framework Many to Many relationship to same entity type but with different relationship type

查看:94
本文介绍了实体框架与相同实体类型但具有不同关系类型的多对多关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用Entity Framework 6,我有一个Person类...

Working with Entity Framework 6, I have a Person class...

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

}

我要代表的意思是,例如,我可以将兄弟姐妹作为一种关系类型,将UnclesAndAunts作为另一种关系类型,并保留这些类型的关系,而无需知道父母的身份,因为他们可能不在数据库中

What I want this to represent is that for example I might have Siblings as a relationship type and UnclesAndAunts as another relationship type and hold these types of relationships without the need to know who the parents are as they may not be in the database.

使用Code First,这将产生一个...的表模式.

With Code First, this produces a table schema of...

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表具有重复数据,例如

The problem with this is that because of the Relationship_ID in the Person table this is saying that the Person table will have repeated data whereas I want the Relationship table to have the repeated data e.g.

Relationship...

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

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

Can someone tell me how I should represent this with the Model Classes, I assume there are some attributes or other that I need to include.

谢谢

推荐答案

Relationship_ID来自Relationship.RelatedPersons集合.我认为这里有一个 collection 是不正确的,相反,它应该是单个 reference RelatedPerson(单数),因为单个Relationship实体描述了完全两个人,而不是在一个人和其他人的集合之间.因此,我建议像这样更改模型:

The Relationship_ID stems from the Relationship.RelatedPersons collection. I think it's not correct to have a collection here, instead it should be a single reference RelatedPerson (singular) since a single Relationship entity describes the relationship between exactly two people, not between a person and a collection of other people. So, I'd propose to change the model like this:

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表中获得三个外键.

The [InverseProperty] attribute is important here to tell EF that Relationship.Person is the inverse navigation property of Person.Relationships. Without that attribute you would get three foreign keys in the Relationship table refering to the Person table.

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

You probably also need to disable cascading delete for one of the relationships to avoid an exception about forbidden multiple cascading delete paths from Person to Relationship. It can be done with Fluent API:

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

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

Once you have that you can add the second relationship with Fluent API as well which would allow you to remove all attributes from the model as they are redundant then:

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

这篇关于实体框架与相同实体类型但具有不同关系类型的多对多关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆