2015-06-06 77 views
1

我正努力在DbContext上實現一個非常基本的「InsertOrUpdate()」方法。我試着按照this post的建議。努力在DbContext上實現通用的InsertOrUpdate()

private static bool SaveItem<TEntity>(Object objToSave, TEntity existing = null) where TEntity : class 
{ 
    try 
    { 
     ///////////////////////////////////////// 
     // BLOCK A 
     if(existing != null) 
      db.Set<TEntity>().Attach(existing); 
     ///////////////////////////////////////// 
     db.Entry(objToSave).State = existing!=null ? EntityState.Modified : EntityState.Added; 
     db.SaveChanges(); 
    } catch(Exception e) 
    { 
     Logger.Exception(e); 
     return false; 
    } 
    return true; 
} 

一個例子調用如下:

SaveItem(item, db.MyInstances.Where(dbItem => dbItem.ID == item.ID).FirstOrDefault()); 

一些定義:

class MyInstancesDbContext: DbContext { ... } 
private static MyInstancesDbContext db = new MyInstancesDbContext(); 

據我瞭解,在撥打.Where()會導致某種形式的附件。所以我已經嘗試了包括標記爲「A」的小塊代碼並將其刪除。這兩者給我同樣的錯誤類型:

System.InvalidOperationException: Attaching an entity of type '...MyInstance' failed because a nother entity of the same type already has the same primary key value. This can happen when using the 'Attach' method or setting the state of an entity to 'Unchanged' or 'Modified' if any en tities in the graph have conflicting key values. This may be because some entities are new and have not yet received database-generated key values. In this case use the 'Add' method or the ' Added' entity state to track the graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.

我發現this popular related answer這個錯誤的用戶建議使用AsNoTracking(),但是這反而讓我覺得我沒有從根本上理解的東西或我試圖忽視一些錯誤。

我非常感謝任何建議。

+0

爲什麼類型的''objToSave'和Object''existing'是'TEntity'?他們不應該一樣嗎? – jjj

回答

0

我想你錯過的是DbContext跟蹤實體,它不喜歡使用相同的主鍵跟蹤相同類型的實體。

  1. 當調用此:

    db.MyInstances.Where(dbItem => dbItem.ID == item.ID).FirstOrDefault() 
    

    已加載的MyInstance與主鍵== item.ID實體進入情境,如果它存在於數據庫中。

  2. 此行完全不需要,因爲existing已經連接 - 但可能不會導致錯誤。

    if(existing != null) 
        db.Set<TEntity>().Attach(existing); 
    
  3. 這個問題可能是在這裏:

    db.Entry(objToSave).State = 
    existing != null ? EntityState.Modified : EntityState.Added; 
    

    如果existing == null,你可能是正確的,因爲這條線將連接objToSave,但如果existing存在,你就會有,因爲你的問題」將嘗試附加與existing具有相同類型和主鍵的objToSave


相反,你可以嘗試使用objToSave爲連接實體設置的值:

db.Entry(existing).CurrentValues.SetValues(objToSave); 

所以objToSave不會,如果有一個現有的記錄連接。

https://msdn.microsoft.com/en-us/data/jj592677.aspx