这个问题通常是由于标识实体框架(Core)的默认行为引起的。默认情况下,当从数据库中加载实体后,标识实体框架(Core)将跟踪该实体所引用的所有导航属性。这意味着如果我们加载一个 Product 实体,并且该实体具有一串 Category 实体,则标识实体框架(Core)将跟踪 Product.Categories 实体,并在保存时自动保存更新。
但是,对于多对多关系,我们必须自己更新中间表。在这种情况下,我们需要指定将被忽略的导航属性。我们可以在 OnModelCreating 方法中配置此设置:
modelBuilder.Entity().HasMany(p => p.Categories).WithMany(c => c.Products).UsingEntity(j => j.ToTable("ProductCategories"));
在这里,我们设定了 Product.Categories 和 Category.Products 属性将被忽略,而 UsingEntity 方法会指定中间表的名称。
以下代码示例演示如何使用此方法更新 Product 实体和其关联的 Category 实体:
private readonly ApplicationDbContext _dbContext;
public ProductService(ApplicationDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task UpdateProductCategoriesAsync(Product product, IEnumerable selectedCategories)
{
_dbContext.Entry(product).State = EntityState.Modified;
product.Categories = selectedCategories.ToList();
await _dbContext.SaveChangesAsync();
}
现在,调用 UpdateProductCategoriesAsync 方法将保存 Product 实体和其关联的 Category 实体,而不会导致未保存的更改。