首页 > 解决方案 > 有没有办法播种 3+ 层级(一对多),包括与 JSON 的自引用关系?

问题描述

我正在构建一个 API,我希望能够从不同的 JSON 文件中播种数据,每个 JSON 文件都包含一个 JSON 树。在我遇到“父母/孩子自我参考”关系之前,它工作得很好。

我创建了一个新的 .NET Core 项目,试图让它在一个包含三个实体的简单解决方案中工作:

    public class Library
    {
        public int LibraryId { get; set; }
        public string Name { get; set; }
        public IEnumerable<Book> Books { get; set; }
    }

    public class Book
    {
        public int BookId { get; set; }
        public string Title { get; set; }
        public IEnumerable<Chapter> Chapters { get; set; }
    }

    public class Chapter
    {
        public int ChapterId { get; set; }
        public string Title { get; set; }
        public Book Book { get; set; }
        public int BookId { get; set; }

        public int? ParentChapterId { get; set; }
        public Chapter ParentChapter { get; set; }
        public IEnumerable<Chapter> ChildrenChapters { get; set; }
    }

数据库上下文:

public DbSet<Library> Libraries { get; set; }
        public DbSet<Book> Books { get; set; }
        public DbSet<Chapter> Chapters { get; set; }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            builder.Entity<Chapter>()
                    .HasMany(p => p.ChildrenChapters)
                    .WithOne(p => p.ParentChapter)
                    .HasForeignKey(p => p.ParentChapterId)
                    .IsRequired(false);

            base.OnModelCreating(builder);
        }

启动.cs:

var dataText = System.IO.File.ReadAllText("Data/JsonSeeding/json.json");
Seeder.SeedFromJson(dataText, app.ApplicationServices);

播种机.cs

    public static class Seeder
    {
        public static void SeedFromJson(string jsonData, IServiceProvider serviceProvider)
        {
            List<Library> collection = JsonConvert.DeserializeObject<List<Library>>(jsonData);

            using (var serviceScope = serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())
            {
                var context = serviceScope
                              .ServiceProvider.GetService<BizDbContext>();
                if (!context.Libraries.Any())
                {
                    context.AddRange(collection);
                    context.SaveChanges();
                }
            }
        }
    }

最后,JSON 文件:

[
  {
    "Name": "Library_1",
    "Books": [
      {
        "Title": "BookTitle1",
        "Chapters": [
          {
            "Title": "Chapter_1",
            "ChildrenChapters": [
              {
                "Title": "Chapter_1_1",
                "ChildrenChapters": [
                  {
                    "Title": "Chapter_1_1_1"
                  },
                  {
                    "Title": "Chapter_1_1_1"
                  },
                  {
                    "Title": "Chapter_1_1_1"
                  }
                ]
              }
            ]
          },
          {
            "Title": "Chapter_2"
          },
          {
            "Title": "Chapter_3"
          }
        ]
      }
    ]
  }
]

它在播种 Library>Book>Chapter 时完美运行,但在添加 ChildrenChapters 时失败:

The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Chapters_Books_BookId". 
The conflict occurred in database "JSONTreeSeedingTest", table "dbo.Books", column 'BookId'.

我理解错误。有没有办法仍然使用相同格式的 JSON 并定义 ChildrenChapters 中的项目应该与 ParentChapter 具有相同的 BookId?

标签: c#jsonentity-framework-coreef-fluent-apiseeding

解决方案


推荐阅读