4.1.实体框架更新多对多关系.这条路对吗?
本文关键字:条路 关系 框架 更新 实体 | 更新日期: 2023-09-27 18:16:58
下面的代码可以工作,但是,我怀疑我遗漏了一些东西。有没有"更好"的方法?
private void UpdateNew(MarketProduct marketproduct)
{
context.MarketCategories.Load();
MarketProduct dbProd = context.MarketProducts.Find(marketproduct.Id);
dbProd.Categories.Clear();
foreach (var c in marketproduct.Categories ?? Enumerable.Empty<MarketCategory>())
{
var cc = context.MarketCategories.Find(c.Id);
dbProd.Categories.Add(cc);
}
context.Entry(dbProd).CurrentValues.SetValues(marketproduct);
}
我认为不使用Find
您有三个数据库查询:1)context.MarketCategories.Load()
(希望类别表很小,否则这将是一个不去,因为它将整个表加载到内存中),2)...Find
和3)dbProd.Categories.Clear()
:这里必须涉及延迟加载,否则这将崩溃,因为dbProd.Categories
将是null
。
使用单个数据库查询进行更新的替代方法如下:
private void UpdateNew(MarketProduct marketproduct)
{
MarketProduct dbProd = context.MarketProducts
.Include(p => p.Categories)
.Single(p => p.Id == marketproduct.Id);
var categories = marketproduct.Categories
?? Enumerable.Empty<MarketCategory>();
foreach (var category in categories)
{
if (!dbProd.Categories.Any(c => c.Id == category.Id))
{
// means: category is new
context.MarketCategories.Attach(category);
dbProd.Categories.Add(category);
}
}
foreach (var category in dbProd.Categories.ToList())
{
if (!categories.Any(c => c.Id == category.Id))
// means: category has been removed
dbProd.Categories.Remove(category);
}
context.Entry(dbProd).CurrentValues.SetValues(marketproduct);
// context.SaveChanges() somewhere
}
我相信你可以这样做:
var dbProd = context.MarketProducts.Find(marketproduct.Id);
dbProd.Categories = dbProd.Categories
.Union(marketproduct.Categories).ToList();
context.SaveChanges();
Union()
调用将保留任何现有产品,添加新产品,并更新重叠的产品。由于您的导航属性Categories
可能被定义为ICollection<Category>
,因此您必须在分配期间使用ToList()
扩展方法。