gpt4 book ai didi

entity-framework-4.1 - 实体 4.1 用新的子实体更新现有的父实体

转载 作者:行者123 更新时间:2023-12-03 10:14:18 25 4
gpt4 key购买 nike

我有一个应用程序,您可以在其中创建一种新型产品并向该产品添加一些成分。产品和成分都是保存在数据库中的实体。产品实体具有成分实体的集合。

(简化版)

public class Product
Public Sub New()
Me.Ingredients = New List(Of Ingredient)()
End Sub

Property Ingredients as ICollection(Of Ingredient)
end class

当我第一次保存产品时,一切顺利:我只是将它添加到上下文中并调用 SaveChanges。
myDataContext.Products.Add(product)
myDataContext.SaveChanges()

产品(父)和成分(子)都被保存并相互链接。一切都很好。

但是,当我向现有产品添加/删除成分时,我开始遇到问题。我首先清除产品实体中现有的成分集合,然后再次添加更新的成分列表(我不重复使用成分添加的时刻)。然后我将产品实体的状态更改为已修改并调用 savechanges。然而,在状态改变时,得到异常“ ObjectStateManager 中已经存在具有相同键的对象”。
myDataContext.Entry(product).State = EntityState.Modified

经过“一些”搜索后,我发现问题在于所有成分的主键都为 0(因为它们尚未添加)并且当您更改父实体(产品)的状态时,所有子实体(成分) 被附加到键为 0 的上下文,这会导致问题,因为键不再是唯一的。

我一直在寻找解决方案,但无法弄清楚如何解决这个问题。我尝试在更改状态之前将成分添加到上下文中,但随后缺少产品和成分之间的链接...如何使用尚未添加的新子实体更新现有父实体?

我使用 Entity Framework 4.1 和代码优先。

希望你能帮我!

最佳答案

I first clear the existing ingredients collection in the product entity and than add the updated list of ingredients again.



嗯,这是更新子集合的一种蛮力攻击。 EF 没有任何更新子级的魔法——这意味着:添加新子级、删除移除的子级、更新现有子级——只需将父级的状态设置为 Modified .基本上这个过程迫使你从数据库中删除旧的 child 并插入新的,像这样:

// product is the detached product with the detached new children collection
using (var context = new MyContext())
{
var productInDb = context.Products.Include(p => p.Ingredients)
.Single(p => p.Id == product.Id);

// Update scalar/complex properties of parent
context.Entry(productInDb).CurrentValues.SetValues(product);

foreach (var ingredient in productInDb.Ingredients.ToList())
context.Ingredients.Remove(ingredient);

productInDb.Ingredients.Clear(); // not necessary probably

foreach (var ingredient in product.Ingredients)
productInDb.Ingredients.Add(ingredient);

context.SaveChanges();
}

更好的方法是更新内存中的子集合而不删除数据库中的所有子集合:

// product is the detached product with the detached new children collection
using (var context = new MyContext())
{
var productInDb = context.Products.Include(p => p.Ingredients)
.Single(p => p.Id == product.Id);

// Update scalar/complex properties of parent
context.Entry(productInDb).CurrentValues.SetValues(product);

var ingredientsInDb = productInDb.Ingredients.ToList();
foreach (var ingredientInDb in ingredientsInDb)
{
// Is the ingredient still there?
var ingredient = product.Ingredients
.SingleOrDefault(i => i.Id == ingredientInDb.Id);

if (ingredient != null)
// Yes: Update scalar/complex properties of child
context.Entry(ingredientInDb).CurrentValues.SetValues(ingredient);
else
// No: Delete it
context.Ingredients.Remove(ingredientInDb);
}

foreach (var ingredient in product.Ingredients)
{
// Is the child NOT in DB?
if (!ingredientsInDb.Any(i => i.Id == ingredient.Id))
// Yes: Add it as a new child
productInDb.Ingredients.Add(ingredient);
}

context.SaveChanges();
}

关于entity-framework-4.1 - 实体 4.1 用新的子实体更新现有的父实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7968598/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com