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(); }
Bassam alugili
source share