在实体框架中处理以下场景的推荐方法是什么?
我在一个名为SessionData
(使用Singleton模式)的类中存储了一些与会话相关的数据。这个类中的一个属性称为Basket
。Basket类有一个BasketItems
的集合。
因此,当篮子初始化时,它会被添加到数据库中并存储在会话中:
var basket = new Basket();
using(var db = new DataContext())
{
db.Baskets.Add(basket);
db.SaveChanges();
}
SessionData.Current.Basket = basket;
然后,当一个购物篮项目被添加到购物篮时:
using(var db = new DataContext())
{
var basketItem = new BasketItem() { initialisation here }
SessionData.Current.Basket.BasketItems.Add(basketItem);
db.SaveChanges();
}
这不起作用,因为SessionData.Current.Basket
未附加到当前DbContext。我尝试过使用:
db.Baskets.Attach(SessionData.Current.Basket)
这在第一次调用时起作用,但在以下调用中失败并出现以下错误:
ObjectStateManager中已存在具有相同键的对象。ObjectStateManager无法跟踪具有相同键的多个对象。
对存储在当前DbContext使用块之外的实体(及其层次结构)执行此更新的建议方法是什么?
在新的数据库上下文中,从数据库中检索购物篮,然后创建新的购物篮项目。
问题是因为当我初始化新BasketItem的属性时,它的一个属性(称为Product
)被DbContext的另一个实例跟踪。我没有发现它,因为我在想Basket类,而不是它的子属性。我通过更改从中获得产品实例的查询来解决这个问题:
var product = (from x in db.Products
where x.ID == basketRequest.ProductID
select x).FirstOrDefault();
至:
var product = (from x in db.Products.AsNoTracking()
where x.ID == basketRequest.ProductID
select x).FirstOrDefault();
它在没有DbContext跟踪的情况下获取实体实例。
Daniel Auger在评论中提到的问题中的链接也帮助我理解了"插入或更新模式",这就是我的问题的真正意义。我不同意这两个问题是重复的,因为它们实际上并不相同。不过链接非常有用!