2011-08-28 82 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; 
    } 
相關問題