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

查看:91
本文介绍了在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*/);

我应该首先添加哪个实体? Books还是Library?我该如何保存?

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天全站免登陆