在 Entity Framework 核心中保存多对多关系
Saving many-to-many relationship in 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; }
}
它们在 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
:
的列表
var library2Books = new List<Library2Books>(/*some sort of initialization*/);
我应该先添加什么实体? Books
或者 Library
?我该如何节省?
对于 EF Core 多对多关系,这是一个简单且非常基础的问题;我不知道为什么没有人在 EF Core 中为 n..m 编写一个完整的示例。
我已经修改了你的代码(主键为int
),我不喜欢主键中的字符串。只需 copy/paste 代码,每个代码都可以正常工作。
What entity should I add first? Books or maybe Library? How can I do this saving?
顺序并不重要,这里重要的是数据链接。数据必须正确链接,请参阅我的代码行之间的注释。
备注:
没有实体 class 来表示联接 table 的多对多关系尚不支持!您必须有一个连接 table.
多对多关系由 2 个独立的一对多关系组成。 = 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 个实体应该足够了。
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();
}
例如,我有 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; }
}
它们在 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
:
var library2Books = new List<Library2Books>(/*some sort of initialization*/);
我应该先添加什么实体? Books
或者 Library
?我该如何节省?
对于 EF Core 多对多关系,这是一个简单且非常基础的问题;我不知道为什么没有人在 EF Core 中为 n..m 编写一个完整的示例。
我已经修改了你的代码(主键为int
),我不喜欢主键中的字符串。只需 copy/paste 代码,每个代码都可以正常工作。
What entity should I add first? Books or maybe Library? How can I do this saving?
顺序并不重要,这里重要的是数据链接。数据必须正确链接,请参阅我的代码行之间的注释。
备注:
没有实体 class 来表示联接 table 的多对多关系尚不支持!您必须有一个连接 table.
多对多关系由 2 个独立的一对多关系组成。 = 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 个实体应该足够了。
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();
}