"ObjectStateManager中已存在具有相同键的对象..."将实体状态设置为已修改时,将引发异常

and*_*rew 12 entity-framework-4 asp.net-mvc-3

我按照一些例子(包括诸如"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();
        }

....
}
Run Code Online (Sandbox Code Playgroud)

此存储库执行更新,如我使用的示例中所示.

产品类别:

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; }
}
Run Code Online (Sandbox Code Playgroud)

在更新产品的情况下,我得到异常"ObjectStateManager中已经存在具有相同键的对象.ObjectStateManager无法跟踪具有相同键的多个对象"

我知道这里已经讨论了类似的问题,但我的问题有点不同:

为什么从示例中获取的代码 不起作用(虽然看起来非常简单明了)?我可能做错了什么或错过了什么.

Sco*_*den 22

在寻找解决方案的几个小时之后,我找到了一个在做了足够的阅读之后看起来合适的方法.

修复程序在这里:

ObjectStateManager中已存在具有相同键的对象.ObjectStateManager无法使用相同的键跟踪多个对象

基本上,从Context中获取记录并调用:

var currentProduct = _context.Products.Find(product.ProductId);    
_context.Entry(currentProduct).CurrentValues.SetValues(product);
Run Code Online (Sandbox Code Playgroud)

在我之前的工作中,这似乎是一个坏主意和我一直讨厌EF的东西,但是在这篇文章中,根据Ladislav Mrnka(他在Stackoverflow上明确回答了每个与EF相关的问题):

实体框架和连接池

EF将在内部存储对实体的请求,因此理想情况下,它将已存在,并且不会再向数据库发出回调.

问题的根本原因似乎是,一旦从Context中获取产品,上下文就会跟踪它,这就是导致所有问题的原因.因此,将您的更改合并回来是唯一的方法.

希望有所帮助.

  • 为了避免这种跟踪,[AsNoTracking()](http://msdn.microsoft.com/en-us/library/gg679352%28v=vs.103%29.aspx)可能会有所帮助. (2认同)