2013-08-18 51 views
1

我已經越來越奇怪的行爲形式實體框架。我正在編寫WebApi應用程序,以便從瀏覽器獲得的對象被斷開/分離。我得到的數據是事務性的,因此它不匹配數據庫中的任何給定表。我必須做一些查找和數據操作才能獲得數據庫上的實際更新。如何處理實體框架中的陳舊緩存?

我似乎遇到的問題是,在查詢數據時,我正在填充「跟蹤更改」緩存。這對我來說似乎不成問題,因爲真正的數據來源應該是數據庫。當我最終使數據發生變化並調用SaveChanges時,我得到了約束錯誤。這是我的步驟。

  1. 查詢數據。
  2. 創建要插入的行。
  3. 將行與db進行比較並進行db更改。

查看Ctx.ChangeTracker.Entries()中的數據後,發現要刪除的條目在應該刪除時標記爲Modified。我周圍的工作方式是爲第3步創建一個新的上下文。它神奇地開始工作。我認爲是這樣,但在我的測試案例中,我從數據庫中進行了最後一次讀取,以驗證我的事務寫入是否正確。我得到了一個應該已經被刪除的額外行。事實上,當直接檢查數據庫。再次做一個新的上下文來解決問題。

我只是假定默認的緩存設置只會用於跟蹤更改而不會加快查詢速度。

如果我嘗試在我的查詢中使用AsNoTracking,我也陷入困境,因爲如果我試圖刪除像這樣查詢的行,我會得到一個錯誤。而在我的代碼中,我不知道我是否要在稍後再刪除或修改。有沒有辦法清除緩存,所以我不需要創建一個新的上下文?

有沒有更好的方法來處理這些問題?

編輯:

AsNoTracking會做的伎倆,在一定程度上。我仍然發現自己實例化更多DbContext的副本以防止錯誤。必須按順序刪除多對一的實體或觸發空外鍵錯誤。

var details = oldInvoice.details.ToList(); 

Context.Entry(oldInvoice).State = EntityState.Unchanged; 
Context.Entry(oldInvoice).State = EntityState.Deleted; 
details.ForEach(a => Context.Entry(a).State = EntityState.Deleted); 
+0

它是一個壞主意,讓您的上下文保持很長一段時間,因爲跟蹤圖在執行很多實體時表現不佳。我的建議是不要在請求之間重複使用你的上下文。這也應該繞過任何併發更新問題 –

回答

1

實體框架提供了一個例外DbUpdateConcurrencyException,你可以捕捉您的通話來SaveChanges()。你可以像這樣循環錯誤:

catch (DbUpdateConcurrencyException ex) 
    { 
     saveFailed = true; 

     // Get the current entity values and the values in the database 
     var entry = ex.Entries.Single(); 
     var currentValues = entry.CurrentValues; 
     var databaseValues = entry.GetDatabaseValues(); 

     // Choose an initial set of resolved values. In this case we 
     // make the default be the values currently in the database. 
     var resolvedValues = databaseValues.Clone(); 

     // Have the user choose what the resolved values should be 
     HaveUserResolveConcurrency(currentValues, databaseValues, 
            resolvedValues); 

     // Update the original values with the database values and 
     // the current values with whatever the user choose. 
     entry.OriginalValues.SetValues(databaseValues); 
     entry.CurrentValues.SetValues(resolvedValues); 
    } 

} while (saveFailed); 

此外,您的更新代碼聽起來也很可疑。通常,當您通過WebApi或其他機制將數據傳遞給客戶端時,返回的數據不具有跟蹤數據,因此應該檢查它是否存在並將其重新附加到上下文並更改其狀態到EntityState.Modified,如果是這樣,請致電SaveChanges()

+0

安德魯謝謝你的答案。你對丟失的跟蹤數據是正確的。所以我完全按照你在底部描述的內容來做。除了之前的查詢混淆了跟蹤數據。 –