多对多自我参照关系 [英] Many-to-many self referencing relationship

查看:89
本文介绍了多对多自我参照关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是EF的新手。而且我遇到了创建多对多自引用关系的问题。
我尝试使用以下解决方案:实体框架核心:与同一实体的多对多关系



我的实体:

 公共类WordEntity 
{
public long Id {get;组; }
公共字符串Name {get;组; }
公用字串Json {get;组; }

公共虚拟List< WordSinonymEntity>别名{组; }
}


公共类WordSinonymEntity
{
public long WordId {get;组; }
公共虚拟WordEntity Word {get;组; }

公共长SinonymId {get;组; }
公共虚拟WordEntity Sinonym {get;组; }
}

和下一个配置:

  modelBuilder.Entity< WordSinonymEntity>()
.HasOne(pt => pt.Sinonym)
.WithMany(p => p。 )
.HasForeignKey(pt => pt.SinonymId);

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

,但是会导致下一个异常。 / p>


System.InvalidOperationException:'无法在'WordEntity.Sinonyms'和'WordSinonymEntity.Word'之间建立关系,因为之间已经存在关系 WordEntity.Sinonyms和 WordSinonymEntity.Sinonym。导航属性只能参与单个关系。’


有人可以帮助我吗?或者可能会建议您学习一些示例?
谢谢。

解决方案

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



每个集合或引用导航属性只能 成为 single 关系的一部分。与显式联接实体的多对多关系是通过 two 一对多关系实现的。 join实体包含两个参考导航属性,但是主实体仅具有 single 集合导航属性,该属性必须与其中一个相关联,但不能与两者相关联。 / p>

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

  public class WordEntity 
{
public long Id {get;组; }
公共字符串Name {get;组; }
公用字串Json {get;组; }

公共虚拟List< WordSinonymEntity>别名{组; }
公共虚拟List< WordSinonymEntity> SinonymOf {get;组; } //<-
}

并通过流畅的API指定关联:

  modelBuilder.Entity< WordSinonymEntity>()
.HasOne(pt => pt.Sinonym)
.WithMany(p => p.SinonymOf)//<-
.HasForeignKey(pt => pt.SinonymId)
.OnDelete(DeleteBehavior.Restrict); //请参阅结尾处的注释

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

另一种方法是保持模型不变,但映射 WordSinonymEntity。与 unidirectional 关联的同义词($ ref $),没有相对应的集合导航属性。

  modelBuilder.Entity< WordSinonymEntity>()
.HasOne(pt => pt.Sinonym)
.WithMany()//<-
.HasForeignKey(pt => pt.SinonymId)
.OnDelete(DeleteBehavior.Restrict); //请参阅结尾处的注释

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

只需确保 WithMany



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


I am new in EF. And I ran into a problem with creation many-to-many self referencing relation. I've tried to use solution from: Entity Framework Core: many-to-many relationship with same entity

my entities :

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 class WordSinonymEntity
{
    public long WordId { get; set; }
    public virtual WordEntity Word { get; set; }

    public long SinonymId { get; set; }
    public virtual WordEntity Sinonym { get; set; }
}

and next configuration:

 modelBuilder.Entity<WordSinonymEntity>()
     .HasOne(pt => pt.Sinonym)
     .WithMany(p => p.Sinonyms)
     .HasForeignKey(pt => pt.SinonymId);

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

but it leads to next exception.

System.InvalidOperationException: 'Cannot create a relationship between 'WordEntity.Sinonyms' and 'WordSinonymEntity.Word', because there already is a relationship between 'WordEntity.Sinonyms' and 'WordSinonymEntity.Sinonym'. Navigation properties can only participate in a single relationship.'

Does anyone can help me or may be suggest some examples to learn ? Thanks.

解决方案

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

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

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

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.

这篇关于多对多自我参照关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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