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

时间:2013-12-26 21:59:17

标签: c# entity-framework entity-framework-6

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

我有一些会话相关数据存储在名为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之外的实体(及其层次结构)进行此更新的推荐方法是什么?

2 个答案:

答案 0 :(得分:1)

在新的db上下文中,从数据库中检索购物篮,然后创建新的购物篮项目。

答案 1 :(得分:1)

问题结果是因为当我初始化新BasketItem的属性时,其中一个属性(称为Product)被另一个DbContext实例跟踪。我没有发现它,因为我正在考虑篮子类,而不是它的子属性。我通过更改查询从中获取产品实例来解决这个问题:

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跟踪的情况下获取实体实例。

The link questionDaniel Auger的评论中提及的{{3}}也帮助我理解了“插入或更新模式”,这正是我的问题所在。我不同意这两个问题是重复的,因为它们并不完全相同。非常有用的链接!