Есть ли способ заполнить иерархические уровни 3+ (один-ко-многим), в том числе отношения самоссылки с JSON? - PullRequest
0 голосов
/ 03 мая 2019

Я создаю API и хотел бы иметь возможность загружать данные из разных файлов 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; }
    }

DbContext:

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

Startup.cs:

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

Seeder.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"
          }
        ]
      }
    ]
  }
]

Отлично работает при заполнении Библиотеки> Книга> Глава, но не работает при добавлении 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 должны иметь тот же BookId, что и ParentChapter?

...