“ObjectStateManager 中已存在具有相同键的对象...”将实体状态设置为已修改时引发异常
Posted
技术标签:
【中文标题】“ObjectStateManager 中已存在具有相同键的对象...”将实体状态设置为已修改时引发异常【英文标题】:"An object with the same key already exists in the ObjectStateManager..." exception is thrown when setting an entity state to modified 【发布时间】:2011-11-05 11:41:28 【问题描述】:我按照一些示例(包括“Pro ASP.NET MVC 3”和“Professional ASP.NET MVC 3”等书籍)使用 EF 4.1 创建简单的 ASP.NET MVC 3 应用程序(因为我是这些应用程序的新手技术)。
我正在使用以下存储库(控制器的所有操作方法都使用它的单个实例)来访问数据库:
public class ProductRepository : IProductRepository
private readonly EFDbContext _context = new EFDbContext();
#region Implementation of IProductRepository
....
public void SaveProduct(Product product)
if (product.ProductId == 0)
_context.Products.Add(product);
else
_context.Entry(product).State = EntityState.Modified;
_context.SaveChanges();
....
此存储库执行更新,如我使用的示例所示。
产品类别:
public class Product
public int ProductId get; set;
public string Name get; set;
public string Description get; set;
public decimal Price get; set;
public string Category get; set;
在更新产品的情况下,我收到异常“ObjectStateManager 中已存在具有相同键的对象。ObjectStateManager 无法跟踪具有相同键的多个对象”
我知道这里已经讨论过类似的问题,但我的问题有点不同:
为什么这段代码取自示例不起作用(尽管它看起来非常简单明了)?我可能做错了什么或错过了什么。
【问题讨论】:
我在使用 Visual Studio 为您设置的默认脚手架时遇到了同样的错误,我无法弄清楚。 【参考方案1】:在寻找解决方案数小时后,我找到了一个经过足够阅读后似乎合适的解决方案。
修复在这里:
An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key
基本上,从上下文中获取记录并调用:
var currentProduct = _context.Products.Find(product.ProductId);
_context.Entry(currentProduct).CurrentValues.SetValues(product);
这似乎是个坏主意,而且我在以前的工作中一直讨厌 EF,但根据 Ladislav Mrnka(他显然回答了 *** 上所有与 EF 相关的问题)在这篇文章中的说法:
Entity Framework and Connection Pooling
EF 将在内部存储对实体的请求,因此理想情况下,它已经存在并且不会对数据库进行额外的回调。
问题的根本原因似乎是,一旦从上下文中获取产品,上下文就会跟踪它,这就是造成所有麻烦的原因。因此,将您的更改重新合并是唯一的方法。
希望对您有所帮助。
【讨论】:
为避免这种跟踪,AsNoTracking() 可能会有所帮助。【参考方案2】:第一次保存项目时,您似乎没有更新 product.ProductId
。这意味着当您再次保存该项目时,它会再次将其添加到上下文中,因此会出现错误。
由于 Id 将由数据库添加(我假设它是自动生成的 Id),因此您需要将产品数据读回客户端。
【讨论】:
【参考方案3】:从泛型的角度来看,这是我最近解决相同问题的方法:
public TEntity Update(TEntity model, bool persist)
if (model == null)
throw new ArgumentException("Cannot update a null entity.");
var updateModel = Get(model.Id);
if (updateModel == null)
return model;
this.context.Entry<TEntity>(updateModel).CurrentValues.SetValues(model);
this.Save(persist);
return model;
【讨论】:
以上是关于“ObjectStateManager 中已存在具有相同键的对象...”将实体状态设置为已修改时引发异常的主要内容,如果未能解决你的问题,请参考以下文章