在 Entity Framework Core 中保存多对多关系 [英] Saving many-to-many relationship in Entity Framework Core

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

问题描述

例如,我有 3 个类,用于多对多关系:

For example, I have 3 classes, which I'm using for many-to-many relationship:

public class Library
{
    [Key]
    public string LibraryId { get; set; }
    public List<Library2Book> Library2Books { get; set; }
}

public class Book
{
   [Key]
   public string BookId { get; set; }
   public List<Library2Book> Library2Books { get; set; }
}

public class Library2Book
{
    public string BookId { get; set; }
    public Book Book { get; set; }

    public string LibraryId { get; set; }
    public Library Library { get; set; }
}

它们在 ApplicationDbContext 中配置:

protected override void OnModelCreating(ModelBuilder builder)
{
    base.OnModelCreating(builder);
    builder.Entity<CodeableConcept2Coding>().HasKey(k => new { k.LibraryId, k.BookId });
    builder.Entity<Library2Book>()
        .HasOne(x => x.Library)
        .WithMany(x => x.Library2Book)
        .HasForeignKey(x => x.LibraryId);
    builder.Entity<Library2Book>()
        .HasOne(x => x.Book)
        .WithMany(x => x.Library2Book)
        .HasForeignKey(x => x.BookId);
}

所以,我想将一些 Library2Books 列表添加到数据库中:

So, I want to add to database some list of Library2Books:

var library2Books = new List<Library2Books>(/*some sort of initialization*/);

我应该先添加什么实体?书籍 还是图书馆?我该如何保存?

What entity should I add first? Books or maybe Library? How can I do this saving?

推荐答案

这是 EF Core 多对多关系的一个简单且非常基础的问题;不知道为什么没有人在EF Core中为n..m写过完整的例子.

This is a simple and a very fundamental question to EF Core many-to-many relationship; I do not know why no one has written a complete example for n..m in EF Core.

我已经修改了您的代码(主键为 int),我不喜欢主键中的字符串.只需复制/粘贴代码,每个代码都可以正常工作.

I have modified your code (primary key as int), I do not like string in primary key. Just copy/paste the code and every should work fine.

我应该先添加什么实体?书籍或图书馆?我该如何保存?

What entity should I add first? Books or maybe Library? How can I do this saving?

顺序并不重要,这里重要的是数据链接.数据必须正确链接,请参阅我的代码行之间的注释.

The order is not important the important thing here is the data linking. The data must be correctly linked, see the comments between my code lines.

注意事项:

  • 尚不支持没有实体类来表示连接表的多对多关系!你必须有一个连接表.

  • Many-to-many relationships without an entity class to represent the join table are not yet supported! You must have a join table.

多对多关系由 2 个独立的一对多关系组成.= 2x 1:N

Many-to-many relationships consists of 2 separate one-to-many relationships. = 2x 1:N

class Program
{
   public class Library
   {
     [Key]
     public int LibraryId { get; set; }
     public List<Library2Book> Library2Books { get; set; } = new    List<Library2Book>();
   }

   public class Book
   {
     [Key]
     public int BookId { get; set; }
     public List<Library2Book> Library2Books { get; set; } = new List<Library2Book>();
   }

   public class Library2Book
   {
     [Key]
     public int BookId { get; set; }
     public Book Book { get; set; }

     [Key]
     public int LibraryId { get; set; }
     public Library Library { get; set; }
   }

   public class MyDbContext : DbContext
   {
     public DbSet<Book> Books { get; set; }

     public DbSet<Library> Libraries { get; set; }

     protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
     {
       optionsBuilder.UseSqlServer(@"Server=.;Database=EFTutorial;integrated security=True;");
       base.OnConfiguring(optionsBuilder);
    }

     protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
       modelBuilder.Entity<Library2Book>().HasKey(k => new { k.LibraryId, k.BookId });

       modelBuilder.Entity<Library2Book>()
           .HasOne(x => x.Book)
           .WithMany(x => x.Library2Books)
           .HasForeignKey(x => x.BookId);

       modelBuilder.Entity<Library2Book>()
          .HasOne(x => x.Library)
          .WithMany(x => x.Library2Books)
          .HasForeignKey(x => x.LibraryId);

       base.OnModelCreating(modelBuilder);
     }
   }

   static void Main(string[] args)
   {
     using (var myDb = new MyDbContext())
    {
      // Create Db
       myDb.Database.EnsureCreated();

       // I will add two books to one library
       var book1 = new Book();
       var book2 = new Book();

       // I create the library 
       var lib = new Library();

       // I create two Library2Book which I need them 
       // To map between the books and the library
       var b2lib1 = new Library2Book();
       var b2lib2 = new Library2Book();

       // Mapping the first book to the library.
       // Changed b2lib2.Library to b2lib1.Library
       b2lib1.Book = book1;
       b2lib1.Library = lib;

       // I map the second book to the library.
       b2lib2.Book = book2;
       b2lib2.Library = lib;

       // Linking the books (Library2Book table) to the library
       lib.Library2Books.Add(b2lib1);
       lib.Library2Books.Add(b2lib2);

       // Adding the data to the DbContext.
       myDb.Libraries.Add(lib);

       myDb.Books.Add(book1);
       myDb.Books.Add(book2);

       // Save the changes and everything should be working!
       myDb.SaveChanges();
     }
   }
}

结果

Tables:   Books    |   Libraries      |    Library2Book  |
           1       |      1           |      1   |   1   |
           2       |      -           |      1   |   2   |

问题作者编辑

当您尝试插入大量实体时(我已经尝试了大约 300 个),您会遇到相同的键已被添加错误.您应该将插入集合拆分为小部分,例如100 个实体应该足够了.

When you're trying to insert a lot of entities (I've tried approximately 300), you'll have the same key has been already added error. You should split your inserting collection into small parts, e.g. 100 entities should be enough.

public async Task SaveEntities(IEnumerable<Library2Book> library2Books)
        {
                int i = 0;
                foreach (var library2Book in library2Books)
                {
                    _dbContext.Set<Library>().Add(codConc2Coding.Library);
                    _dbContext.Set<Book>().Add(codConc2Coding.Book);
                    _dbContext.Set<Library2Book>().Add(library2Book);
                    i++;
                    if (i == 99)
                    {
                        await _dbContext.SaveChangesAsync();
                        i = 0;
                    }
                }
                await _dbContext.SaveChangesAsync();
}

这篇关于在 Entity Framework Core 中保存多对多关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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