c# - mvc - Relacionamento auto-referenciamento many-to-many



many to many crud mvc (1)

Eu sou novo na EF. E eu tive um problema com a criação da relação de auto-referência muitos-para-muitos. Eu tentei usar a solução de: Entity Framework Core: muitos-para-muitos relacionamento com a mesma entidade

minhas entidades:

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

e próxima configuração:

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

mas leva à próxima exceção.

System.InvalidOperationException: 'Não é possível criar um relacionamento entre' WordEntity.Sinonyms 'e' WordSinonymEntity.Word ', porque já existe um relacionamento entre' WordEntity.Sinonyms 'e' WordSinonymEntity.Sinonym '. As propriedades de navegação só podem participar de um único relacionamento.

Alguém pode me ajudar ou pode sugerir alguns exemplos para aprender? Obrigado.


O post que você está seguindo está definitivamente errado.

Cada coleção ou propriedade de navegação de referência pode fazer parte de um único relacionamento. Enquanto muitos a muitos relacionamento com entidade de junção explícita é implementado com dois um para muitos relacionamentos. A entidade de junção contém duas propriedades de navegação de referência, mas a entidade principal possui apenas uma propriedade de navegação de coleta, que deve estar associada a uma delas, mas não a ambas.

Uma maneira de resolver o problema é adicionar uma segunda propriedade de navegação de coleção:

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

e especifique as associações via API fluente:

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

Outra maneira é deixar o modelo como está, mas mapear o WordSinonymEntity.Sinonym para associação unidirecional (com a propriedade de navegação de referências e nenhuma propriedade de navegação de coleção correspondente):

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

Apenas certifique-se de que WithMany corresponda exatamente à presença / ausência da propriedade de navegação correspondente.

Observe que, em ambos os casos, é necessário desativar a exclusão em cascata para pelo menos um dos relacionamentos e excluir manualmente as entidades de união relacionadas antes de excluir a entidade principal, porque os relacionamentos de auto-referência sempre introduzem possíveis ciclos ou vários caminhos em cascata , impedindo o uso de cascata excluir.