Asp.net mvc 3 &引用;ObjectStateManager中已存在具有相同密钥的对象…“;将实体状态设置为“已修改”时引发异常

Asp.net mvc 3 &引用;ObjectStateManager中已存在具有相同密钥的对象…“;将实体状态设置为“已修改”时引发异常,asp.net-mvc-3,entity-framework-4,Asp.net Mvc 3,Entity Framework 4,我按照一些示例(包括“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 = ne

我按照一些示例(包括“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无法跟踪具有相同密钥的多个对象”

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


为什么取自示例的代码不起作用(尽管它看起来非常简单和直接)?我可能做错了什么或错过了什么。

第一次保存项目时,您似乎没有更新
product.ProductId
。这意味着,当您再次返回保存项目时,它会再次将其添加到上下文中,因此会出现错误


由于该Id将由数据库添加(我假设它是自动生成的Id),因此您需要将产品数据读回客户端。

在搜索了几个小时的解决方案后,我在阅读了足够的内容后找到了一个似乎合适的解决方案

修复方法如下:

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

var currentProduct = _context.Products.Find(product.ProductId);    
_context.Entry(currentProduct).CurrentValues.SetValues(product);
这似乎是一个坏主意,在我以前的工作中我一直讨厌EF,但根据Ladislav Mrnka(他显然回答了与Stackoverflow有关的所有EF问题)在这篇文章中的说法:

EF将在内部存储对实体的请求,因此理想情况下,它已经存在,并且不会对数据库进行额外的回调

问题的根本原因似乎是,一旦从上下文中提取产品,上下文就会跟踪它,这就是造成所有问题的原因。因此,将更改合并回是唯一的方法


希望这能有所帮助。

从泛型的角度来看,我最近是如何解决同样的问题的:

    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;
    }
public tenty更新(tenty模型,bool persist)
{
if(model==null)
{
抛出新ArgumentException(“无法更新空实体”);
}
var updateModel=Get(model.Id);
if(updateModel==null)
{
收益模型;
}
this.context.Entry(updateModel).CurrentValues.SetValues(model);
这个。保存(持久化);
收益模型;
}

我在使用Visual Studio为您设置的默认支架时遇到了相同的错误,但我无法解决。若要避免此跟踪,可能会有所帮助。