正在更新存储在当前DbContext外部的实体



在实体框架中处理以下场景的推荐方法是什么?

我在一个名为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在评论中提到的问题中的链接也帮助我理解了"插入或更新模式",这就是我的问题的真正意义。我不同意这两个问题是重复的,因为它们实际上并不相同。不过链接非常有用!

最新更新