Базовая модель Entity Framework с иерархией одной и той же таблицы

#c# #asp.net-core #entity-framework-core

Вопрос:

Я использую ASP.NET Основной веб-API с .NET 5 и Entity Framework Core 5.

У меня есть таблица Article с некоторыми свойствами, и я пытаюсь понять, что статья может содержать другие статьи. Как иерархия или какой-то «Перечень материалов».

Я не хочу создавать дополнительные таблицы, например SubArticle , потому что они могут быть вложены несколько раз.

Я думал о создании таблицы сопоставления ArticleHierarchy , которая также используется для отношений M2M, но только с одной таблицей, возможно ли это?

 public class Article {  [Key]  public int Id { get; set; }  public string Name{ get; set; }   public string SomeProperties { get; set; }    public virtual ICollectionlt;ArticleHierarchygt; ArticleHierarchies { get; set; }  }  public class ArticleHierarchy {  [DatabaseGenerated(DatabaseGeneratedOption.Identity)]  public int Id { get; set; }  [ForeignKey(nameof(ParentArticle))]  public int ArticleParentId { get; set; }  [ForeignKey(nameof(ChildArticle))]  public int ArticleChildId { get; set; }   public virtual Article ParentArticle { get; set; }  public virtual Article ChildArticle { get; set; } }  

Это правильный путь, и если да, то как должны выглядеть мои занятия?

Или есть еще лучший способ сделать это?

Спасибо

Ответ №1:

вы должны исправить отношения, добавить

 public class Article {  [Key]  public int Id { get; set; }  public string Name{ get; set; }   public string SomeProperties { get; set; }     [InverseProperty(nameof(ArticleHierarchy.ChildArticle))]  public virtual ICollectionlt;ArticleHierarchygt; ChildArticleHierarchies { get; set; }    [InverseProperty(nameof(ArticleHierarchy.ParentArticle))]  public virtual ICollectionlt;ArticleHierarchygt; ParentArticleHierarchies { get; set;}   }  public class ArticleHierarchy {  [Key]  public int Id { get; set; }    public int ArticleParentId { get; set; }    public int ArticleChildId { get; set; }   [ForeignKey(nameof(ParentArticleId))]  [InverseProperty("ParentArticleHierarchies")]  public virtual Article ParentArticle { get; set; }   [ForeignKey(nameof(ChildArticleId))]  [InverseProperty("ChildArticleHierarchies")]  public virtual Article ChildArticle { get; set; } }  

Комментарии:

1. Мне нужно было добавить modelBuilder.Entitylt;ArticleHierarchygt;() .HasKey(e =gt; new { e.ArticleChildId, e.ArticleParentId }); , потому что я получил ошибку при запуске миграции. Теперь миграция выполняется, но когда я запускаю «обновление базы данных», я получаю следующую ошибку: Введение ограничения ВНЕШНЕГО КЛЮЧА «FK_ArticleHierarchy_Article_ArticleParentId» в таблице «ArticleHierarchy» может привести к циклам или нескольким каскадным путям. Укажите ПРИ УДАЛЕНИИ БЕЗ ДЕЙСТВИЯ или ПРИ ОБНОВЛЕНИИ БЕЗ ДЕЙСТВИЯ или измените другие ограничения ВНЕШНЕГО КЛЮЧА. Не удалось создать ограничение или индекс. См. Предыдущие ошибки

2. @AnNormalie Удалить конструктор моделей. Сущностьlt;ArticleHierarchygt;() .hasKey(e =lt;ArticleHierarchygt;gt; новый { e.ArticleChildId, e.ArticleParentId }) и сделайте идентификатор в качестве ключа, см. Мой ответ.

3. это помогло устранить ошибку миграции без необходимости кода FluentAPI. Но я все равно получаю ошибку, когда запускаю обновление базы данных. Я исправил это с помощью modelBuilder.Entitylt;Articlegt;() .HasMany(e =gt; e.ParentArticleHierarchies) .WithOne(e =gt; e.ParentArticle) .OnDelete(DeleteBehavior.Restrict); modelBuilder.Entitylt;Articlegt;() .HasMany(e =gt; e.ChildArticleHierarchies) .WithOne(e =gt; e.ChildArticle) .OnDelete(DeleteBehavior.Restrict);