Yur*_* N. 23 c# many-to-many entity-framework-core
例如,我有3个类,我用它们用于多对多关系:
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; }
}
Run Code Online (Sandbox Code Playgroud)
它们配置为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);
}
Run Code Online (Sandbox Code Playgroud)
所以,我想在数据库中添加一些列表Library2Books:
var library2Books = new List<Library2Books>(/*some sort of initialization*/);
Run Code Online (Sandbox Code Playgroud)
我应该先添加什么实体?Books或许Library?我怎么能这样做?
Bas*_*ili 43
对于EF Core多对多关系来说,这是一个简单而又非常基本的问题; 我不知道为什么没有人在EF Core中为n..m编写完整的例子.
我修改了你的代码(主键为int),我不喜欢主键中的字符串.只需复制/粘贴代码,每个都应该正常工作.
我应该先添加什么实体?书籍还是图书馆?我怎么能这样做?
顺序并不重要,重要的是数据链接.必须正确链接数据,请参阅我的代码行之间的注释.
笔记:
尚不支持没有实体类来表示连接表的多对多关系!您必须有一个联接表.
多对多关系由两个独立的一对多关系组成.= 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();
     }
   }
}
Run Code Online (Sandbox Code Playgroud)结果
Tables:   Books    |   Libraries      |    Library2Book  |
           1       |      1           |      1   |   1   |
           2       |      -           |      1   |   2   |
Run Code Online (Sandbox Code Playgroud)
从问题的作者编辑
当你试图插入很多实体时(我已经尝试了大约300个实体),你已经添加了相同的密钥错误.您应该将插入的集合拆分成小部分,例如100个实体就足够了.
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();
}
Run Code Online (Sandbox Code Playgroud)
        |   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           15162 次  |  
        
|   最近记录:  |