0

在我的MVC應用程序中,我一直在使用Repository模式進行DAL。存儲庫模式在更新記錄時發生異常

現在,當我做了選擇一個實體記錄,並更新實體字段值,並執行更新操作,然後得到以下錯誤。

附加一個'DAL.User'類型的實體失敗,因爲另一個相同類型的實體 已經具有相同的主鍵值。如果圖中的任何實體具有 衝突的鍵值,則使用「附加」方法或將實體的狀態設置爲「未更改」或「已修改」時會發生此問題 。這可能是因爲某些實體是新的,並且 尚未收到數據庫生成的密鑰值。在這種情況下,使用 'Add'方法或'Added'實體狀態跟蹤圖形,然後將非新實體的狀態設置爲'Unchanged'或'Modified',因爲 正確。「} System.Exception

下面是倉庫的東西:

public void Update(TEntity entity) 
{ 
    if (_context.Entry(entity).State != EntityState.Modified) 
    { 
     _dbSet.Attach(entity); 
     _context.Entry(entity).State = EntityState.Modified; 
    } 
} 

調用如下: 在Bussines層庫: Manager類:

private readonly IUnitOfWork _unitOfWork; 
    private IRepository <User , int> UserRepository 
    { 
     get 
     { 
      return _unitOfWork.GetRepository<AccountUser, int>(); 
     } 
    } 
    public void UpdateUserEntity(UserDTO u) 
    { 
     try 
     { 

      User model = new User(); 
      UserRepository.Update(Mapper.Map(u, model)); 
      _unitOfWork.SaveChanges(); 
     } 
     catch (Exception ex) 
     { 
      throw; 
     } 
    } 

請指導我如何解決上述錯誤。

+0

Update()方法的Tentity參數來自哪裏?它是從數據庫中讀取,修改並正在嘗試保存回數據庫的對象嗎?或者它是通過將數據發佈到應用程序中的某個Web端點而創建的模型對象? – 2014-09-03 05:35:53

+0

請在經理層的東西找到問題。 – user3711357 2014-09-03 05:46:38

+0

你可能看看我的答案[ASP.NET MVC - 附加一個類型'MODELNAME'的實體失敗,因爲另一個相同類型的實體已經有相同的主鍵值](http://stackoverflow.com/questions/23201907/ASP淨MVC附着-AN-實體的型MODELNAME失敗的 - 因爲-另一個-ENT/39557606#39557606)。 – 2016-09-18 12:36:07

回答

0

這是因爲這個原因, 「TEntity實體作爲一個新對象,而不是已經存在的實體」。手段,實體框架將每個新對象視爲新條目(儘管使用相同的舊數據,所有PK &)。

解決方案是,

首先從數據庫中檢索對象

DO /分配更改到相同的對象(優選不改變主鍵)

然後執行狀態修改,更新,SaveChange()

+0

它已經在那裏,因爲我首先檢索,然後在UI上填充和用戶界面將更新值,然後調用上面顯示的更新方法。請檢查更新quesiton與管理層的東西。 – user3711357 2014-09-03 05:45:17

3

該例外說明存在另一個實體具有已連接的相同密鑰,但是di不同的參考。

  • 該異常可能是由以前的附屬實體造成的。

    db.Set<Entity>().Attach(new Entity { Id = 123 }); 
    db.Set<Entity>().Attach(new Entity { Id = 123 }); // different reference but same key 
    
  • 或者也可能是由被跟蹤的實體自動附加引起的。

    db.Set<Entity>().FirstOrDefault(e => e.Id == 123); // automatically attached 
    db.Set<Entity>().Attach(new Entity { Id = 123 }); // different reference but same key 
    

第二個原因可以通過檢索項目時提AsNoTracking來解決。

db.Set<Entity>().AsNoTracking().FirstOrDefault(e => e.Id == 123); 

或者爲了安全起見,您可以使用此擴展名來始終分離任何附加的實體。

public static class DbSetExtension 
{ 
    public static void SafeAttach<T>(
     this DbContext context, 
     T entity, 
     Func<T, object> keyFn) where T : class 
    { 
     var existing = context.Set<T>().Local 
      .FirstOrDefault(x => Equals(keyFn(x), keyFn(entity))); 
     if (existing != null) 
      context.Entry(existing).State = EntityState.Detached; 

     context.Set<T>().Attach(entity); 
    } 
} 

用法。

db.SafeAttach(entity, e => e.Id); 
+0

SafeAttach是我一直在尋找的 - 謝謝! – 2014-10-10 13:28:43

+0

即使現有實體的狀態更改爲已分離,您是否還有任何評論?附加新的錯誤仍會引發錯誤。 – ocanal 2018-01-26 08:45:26