简体   繁体   English

如何使M:N(多对多)关系,其中M和N是相同的实体?

[英]How to make M:N (many-to-many) relationship where both M and N are the same entities?

I am having difficulties with Entity Framework. 我在实体框架方面遇到了困难。 I am trying to set up datamodel with entity refering to its opposite via a connection table. 我试图通过连接表通过实体引用其对面来设置datamodel。

I have created an entity Style and connection table StyleXStyle. 我创建了一个实体样式和连接表StyleXStyle。

[Table("Styles")]
public class Style : FullAuditedEntity
{
    public virtual string Name { get; set; }

    public virtual string ShortName { get; set; }

    public List<StyleXStyle> Opposites { get; set; } = new List<StyleXStyle>();
}
[Table("StylesXStyles")]
public class StyleXStyle: FullAuditedEntity
{
    public virtual int StyleId { get; set; }
    public Style Style { get; set; }

    public virtual int OppositeId { get; set; }
    public Style Opposite { get; set; }
}

When I try to add database migration, I got this error: 当我尝试添加数据库迁移时,我收到此错误:

Unable to determine the relationship represented by navigation property 'Style.Opposites' of type 'List<StyleXStyle>'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.

Since you need to self-refer to a collection of Style entities you should have 2 collection properties for this many-to-many mapping. 由于您需要自我引用Style实体的集合,因此您应该为此多对多映射提供2个集合属性。 One to navigate to your opposites and one to "alikes". 一个导航到你的对立面,一个导航到“相似”。 For my examples I am including a second list property called Alikes . 对于我的例子,我包括一个名为Alikes的第二个列表属性。

With that you can include a custom mapping to tell EF how these are related: 有了它,您可以包含一个自定义映射,告诉EF这些是如何相关的:

Using attribute-based config: 使用基于属性的配置:

public class Style : FullAuditedEntity
{   
    [InverseProperty("Style")] 
    public List<StyleXStyle> Alikes { get; set; } = new List<StyleXStyle>();
    [InverseProperty("Opposite")]
    public List<StyleXStyle> Opposites { get; set; } = new List<StyleXStyle>();
}

public class StyleXStyle : FullAuditedEntity
{
    [ForeignKey("Opposite")]
    public virtual int OppositeId { get; set; }
    public Style Opposite { get; set; }

    [ForeignKey("Style")]
    public virtual int StyleId { get; set; }
    public Style Style { get; set; }
}

Using Fluent API: 使用Fluent API:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // configures one-to-many relationship
    modelBuilder.Entity<StyleXStyle>()
        .HasRequired<Style>(s => s.Style)
        .WithMany(g => g.Alikes)
        .HasForeignKey<int>(s => s.StyleId);          

    // configures one-to-many relationship
    modelBuilder.Entity<StyleXStyle>()
        .HasRequired<Style>(s => s.Opposite)
        .WithMany(g => g.Opposites)
        .HasForeignKey<int>(s => s.OppositeId);          
}

The above performs the mapping on the joining entity/table so you can use that as your many-to-many relation. 以上操作在连接实体/表上执行映射,因此您可以将其用作多对多关系。 This is necessary if you need to track any information on the relation itself (for example, CreatedDate, CreatedBy, RelationDate, etc.), however, EF provides its own way to map this by convention IF you don't require additional information on the relation entity. 如果您需要跟踪关系本身的任何信息(例如,CreatedDate,CreatedBy,RelationDate等),这是必要的,但是,EF提供了自己的方式来按照约定映射它如果您不需要关于关系的其他信息关系实体。

In the latter case, you can map your entities directly to each other and omit the relation table altogether. 在后一种情况下,您可以直接将实体映射到彼此,并完全省略关系表。 Here is a quick example: 这是一个简单的例子:

[Table("Styles")]
public class Style : FullAuditedEntity
{
    public virtual string Name { get; set; }

    public virtual string ShortName { get; set; }

    public ICollection<Style> Opposites { get; set; }
    public ICollection<Style> Alikes { get; set; }
}

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{

    modelBuilder.Entity<Style>()
                .HasMany<Style>(s => s.Alikes)
                .WithMany(c => c.Opposites)
                .Map(cs =>
                        {
                            cs.MapLeftKey("OppositeId");
                            cs.MapRightKey("StyleId");
                            cs.ToTable("StyleXStyle");
                        });

}

The code above was put together for your example, I did not fully test it but have implemented this the same way before. 上面的代码放在一起作为你的例子,我没有完全测试它,但之前以相同的方式实现了它。

HTH HTH

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 MVC3中相同类型的实体之间的多对多关系 - Many-to-many relationship between entities of same type in MVC3 如何创建多对多关系实体并为它们播种? - How to create Many-to-Many relationship entities and seed them? 使用实体的多对多关系查询 - Many-to-Many relationship query using entities 如何为双方具有相同父级的多对多实施EF连接表 - How to implement EF join table for many-to-many where both sides have same parent LINQ多对多关系,如何编写正确的WHERE子句? - LINQ many-to-many relationship, how to write a correct WHERE clause? 如何在同一实体上创建多对多关系? - How to create many-to-many relationship on the same entity? 在EF中没有联接表的情况下,如何在具有多对多关系的两个表(实体)之间使用LINQ进行JOIN查询? - How can I make a JOIN query with LINQ between two tables (entities) with many-to-many relationship, while there is no joining table in EF? 同一类之间的多对多关系 - Many-to-many relationship between the same class 如何使用清单在EF关系另一侧的实体集合中更新多对多关系<TEntity> - How to update a many-to-many relationship with a collection of entities that are on the other side of the relationship in EF with a List<TEntity> 这是多对多关系吗? - Is this a many-to-many relationship?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM