且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

多对多自引用关系

更新时间:2022-12-30 18:19:01

您关注的帖子肯定是错误的.

The post you are following is definitely wrong.

每个集合或引用导航属性只能成为单个关系的一部分.而具有显式连接实体的多对多关系是通过两个一对多关系实现的.连接实体包含两个引用导航属性,但主实体只有单个集合导航属性,必须与其中之一相关联,但不能同时与两者相关联.

Every collection or reference navigation property can only be a part of a single relationship. While many to many relationship with explicit join entity is implemented with two one to many relationships. The join entity contains two reference navigation properties, but the main entity has only single collection navigation property, which has to be associated with one of them, but not with both.

解决该问题的一种方法是添加第二个集合导航属性:

One way to resolve the issue is to add a second collection navigation property:

public class WordEntity
{
    public long Id { get; set; }
    public string Name { get; set; }
    public string Json { get; set; }

    public virtual List<WordSinonymEntity> Sinonyms { get; set; }
    public virtual List<WordSinonymEntity> SinonymOf { get; set; } // <--
}

并通过 fluent API 指定关联:

and specify the associations via fluent API:

modelBuilder.Entity<WordSinonymEntity>()
     .HasOne(pt => pt.Sinonym)
     .WithMany(p => p.SinonymOf) // <--
     .HasForeignKey(pt => pt.SinonymId)
     .OnDelete(DeleteBehavior.Restrict); // see the note at the end

modelBuilder.Entity<WordSinonymEntity>()
    .HasOne(pt => pt.Word)
    .WithMany(t => t.Sinonyms)
    .HasForeignKey(pt => pt.WordId); 

另一种方法是保持模型不变,但将 WordSinonymEntity.Sinonym 映射到 单向 关联(具有参考导航属性,没有相应的集合导航属性):

Another way is to leave the model as is, but map the WordSinonymEntity.Sinonym to unidirectional association (with refeference navigation property and no corresponding collection navigation property):

modelBuilder.Entity<WordSinonymEntity>()
     .HasOne(pt => pt.Sinonym)
     .WithMany() // <--
     .HasForeignKey(pt => pt.SinonymId)
     .OnDelete(DeleteBehavior.Restrict); // see the note at the end

modelBuilder.Entity<WordSinonymEntity>()
    .HasOne(pt => pt.Word)
    .WithMany(t => t.Sinonyms)
    .HasForeignKey(pt => pt.WordId); 

只需确保 WithMany 与相应导航属性的存在/不存在完全匹配.

Just make sure that WithMany exactly matches the presence/absence of the corresponding navigation property.

请注意,在这两种情况下,您必须为至少一个关系关闭删除级联,并在删除主实体之前手动删除相关的连接实体,因为自引用关系总是会引入可能的循环或多个级联路径问题,阻止使用级联删除.

Note that in both cases you have to turn the delete cascade off for at least one of the relationships and manually delete the related join entities before deleting the main entity, because self referencing relationships always introduce possible cycles or multiple cascade path issue, preventing the usage of cascade delete.