2011-08-28 57 views
12

“ObjectStateManager中已存在具有相同密钥的对象...”异常引发我遵循一些示例(包括诸如“Pro ASP.NET MVC 3”和“Professional ASP .NET MVC 3“)使用EF 4.1创建简单的ASP.NET MVC 3应用程序(因为我是这些技术的新手)。设置实体状态为已修改

我使用以下信息库(它单个实例由控制器使用的所有操作方法)来访问DB:

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不能用相同的跟踪多个目标。关键”

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

为什么这段代码这是从拍摄为例es不工作(虽然它看起来非常简单和直接)?我可能做了什么或错过了什么。

+0

我使用的Visual Studio会为您设置默认脚手架具有同样的错误,我一直没能弄明白。 –

回答

22

在寻找解决方案的几小时后,我发现在做足够的阅读后似乎适合。

的修复是在这里:

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(谁在Stackoverflow上回答了每个EF相关的问题):

Entity Framework and Connection Pooling

EF将存储实体的请求在内部,因此理想情况下,它已经在那里,它不会作出额外的电话回数据库。

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

希望有所帮助。

+2

为避免此跟踪,[AsNoTracking()](http://msdn.microsoft.com/zh-cn/library/gg679352%28v=vs.103%29.aspx)可能会有所帮助。 –

3

看起来你并没有更新product.ProductId当这个项目第一次被保存。这意味着,当您再次保存该项目时,它会再次将其添加到上下文中,因此出现错误。

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

0

从泛型的角度看,这里就是我有非常最近解决了同样的问题:

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; 
    } 
相关问题