在实体框架中处理以下场景的推荐方法是什么?
我有一些会话相关数据存储在名为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之外的实体(及其层次结构)进行此更新的推荐方法是什么?
答案 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 question中Daniel Auger的评论中提及的{{3}}也帮助我理解了“插入或更新模式”,这正是我的问题所在。我不同意这两个问题是重复的,因为它们并不完全相同。非常有用的链接!