Maintain many-to-many relationships in the Entity Framework Core

For example, I have 3 classes that I used for many-to-many relationships:

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

They are configured in 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); } 

So, I want to add some list of Library2Books :

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

Which entity should I add first? Books or maybe a Library ? How to do it?

+8
c # many-to-many entity-framework-core
source share
1 answer

This is a simple and very fundamental question for an EF Core many-to-many relationship; I don't know why no one wrote a complete example for n..m in EF Core. I have lite bite that changed your code (primary key as Int), I don't like the string in the primary key. You only need to copy / paste the code, and each 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 data connection is important here. The data must be correctly connected, see Comments between my code lines.

Notes:

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

  • The many-to-many relationship consists of two 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. b2lib1.Book = book1; b2lib2.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(); } } } 

results

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

Edit from the author of the question

When you try to insert many objects (I tried about 300, that was enough), you will have the same key that already added the error. You need to split your plugin collection into small parts, for example. 100 objects will 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(); } 
+14
source share

All Articles