4

我有一個實體框架4.0模型實現與純POCO(沒有代碼生成,沒有自我跟蹤的實體,只是普通的舊CLR對象)。更新操作問題在實體框架4(純POCO)

現在,這裏是一些代碼,我有我的UI執行UPDATE:

[HttpPost] 
public ActionResult UpdatePerson(Person person) 
{ 
    repository.Attach(person); 
    unitOfWork.Commit(); 
} 

從本質上講,我有接受一個強類型的Person對象的操作方法,以及我需要更新這個實體。

不會出錯,但也不會將更改持久保存到數據庫中。 :(

當我檢查EntityState在我工作的單位的 「提交」:

var entities = ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Deleted | EntityState.Modified | EntityState.Unchanged); 

我看到我的實體,與EntityState.Unchanged

這樣解釋道。爲什麼它沒有被保留我的查找,添加,刪除操作工作正常(堅持正確)但更新似乎並沒有工作

我找到了一些線程sayin G I需要手動設置對象的狀態:

ctx.ObjectStateManager.ChangeObjectState(person, EntityState.Modified); 

是正確的嗎?我會把這個邏輯放在哪裏?在我的工作單位上公開作爲一項操作?

顯然問題是我有無變化跟蹤由於使用Pure POCO(沒有EntityObject派生,沒有INotifyPropertyChanging實現)。

但直到現在我還沒有發現它的問題。

我在做什麼錯了?

回答

2

那麼,由於您沒有任何更改跟蹤等,所以在調用SaveChanges()時,EF應該有方法確定如何處理附屬實體。默認情況下,EntityState不變,所以如果你想更新,你必須手動設置狀態。

另一種方法是使用此Id查詢Person,使用從控制器獲取的數據重寫屬性,並調用SaveChanges()。實際上這是一種更安全的方式,因爲您可以防止在用戶編輯Webform時刪除Person的情況;但這顯然需要額外往返DB,往往不太理想。

在任何情況下,我想有一個倉庫Update()方法(比Attach更具體的),這將真正重視實體,改變EntityStateModified。你的行動中仍然有相對乾淨的代碼:

public ActionResult UpdatePerson(Person person) 
{ 
    repository.Update(person); 
    unitOfWork.Commit(); 
} 
+0

是的,我真的不想做額外的往返旅行。所以我們必須手動設置EntityState(就像我預測的那樣)。很酷,謝謝。另外 - 我在想 - 有沒有一種方法的「更新」方法可以足夠聰明,弄清楚它是一個更新或INSERT?(即檢查PersonId,如果其> 0,它是一個更新,否則一個INSERT?)或是太瘋狂/可怕。如果一個方法可以處理這兩種情況,那將會很好。可能? – RPM1984 2010-10-26 08:01:41

+0

據我所知,你正在談論你要創建的'Update()'方法,所以你可以使它像你想的那樣聰明;)例如,附加實體,然後檢查if(Person.Id == 0){/ *將狀態更改爲Added * /} else {/ *將狀態更改爲Modified * /}'。不過,我不確定這是一個好主意。有單獨的插入和更新方法通常更具可讀性。你爲什麼要合併成一個? – Yakimych 2010-10-26 08:22:43

+0

因爲我使用的是MVC,並且添加/修改Person實體的操作是相同的(HTTP POST,通過強類型對象)。所以我無法知道它是一個添加還是更新(當然,我可以通過一個額外的標誌)。我同意,但我將它們分離出來,可能必須通過HTTP POST中的隱藏字段,說明它是一個添加/更新。謝謝 – RPM1984 2010-10-26 21:23:38