2013-03-03 30 views
0

爲什麼我的ASP.NET MVC3 Edit行動被賦予一個新的對象,而不是編輯的對象?
當我檢查給定的對象的屬性值是我在我的NHibernate映射文件中指定的unsaved-valueNHibernate + MVC3編輯ActionResult - 行更新或刪除/ StaleObjectException

爲了解決這個問題,我可以查詢從數據庫更新的對象並設置傳遞給方法的對象所需的屬性。但是,雖然這對一個具有一個或兩個屬性的非常簡單的對象很有用,但當有很多屬性時,它很快就會成爲一個問題,並且看起來像我在與系統進行對戰(對我而言,這表明我沒有做到事情的方式,他們應該完成)。

我的映射:

<id name="Id" column="Id" type="Guid" 
    unsaved-value="00000000-0000-0000-0000-000000000000"> 

我的編輯方法,包括:

[NHibernateActionFilter] 
[HttpPost] 
public ActionResult Edit(Status status, Guid id) 
{ 
    try 
    { 
     if (ModelState.IsValid) 
     { 
      var originalStatus = Session.QueryOver<Status>() 
             .Where(s => s.Id == id) 
             .SingleOrDefault<Status>(); 
      if (originalStatus == null) 
       throw new Exception(string.Format("No Status with Id: {0}.", id)); 

      originalStatus.StatusName = status.StatusName; 
      Session.Update(originalStatus); 

      return RedirectToAction("Index"); 
     } 
    } 
    catch (DataMisalignedException ex) 
    { 
     // TODO: Log4Net this 
     ModelState.AddModelError("", "Unable to save changes. Please try again."); 
    } 
    return View(status); 
} 

*的NHibernateActionFilter由一系列由Ayende帖子的採取Refactoring toward frictionless & odorless code並給出一個ISession在控制器的每個動作的裝飾用它。但我不認爲這是問題的原因。嘗試編輯項目時

我的問題出現,一StaleObjectException拋出:[TheWorkshop.Web.Models:

行被另一個事務(或未保存的值的映射是不正確的),更新或刪除。狀態#00000000-0000-0000-0000-000000000000]

新的Guid顯示我提到的狀態是新的,而不是先前返回的對象以填充細節視圖。所以看起來新的對象已經被發現並傳入我的編輯ActionResult,但這沒有幫助。

正如我上面所顯示的,我可以對它進行編碼,但這更像是一種解決方案。我寧願能留下我的編輯方法,像這樣:

[NHibernateActionFilter] 
[HttpPost] 
public ActionResult Edit(Status status) 
{ 
    try 
    { 
     if (ModelState.IsValid) 
     { 
      Session.Update(status); 

      return RedirectToAction("Index"); 
     } 
    } 
    catch (DataMisalignedException ex) 
    { 
     // TODO: Log4Net this 
     ModelState.AddModelError("", "Unable to save changes. Please try again."); 
    } 
    return View(status); 
} 

編輯
我已經看過the answer How to handle update entities. NHibernate + ASP.NET MVC但確實差不多就是我已經做了,我不能相信更新方法必須像我的嘗試那麼混亂。

我也看過what does this error mean in nhibernate;它看起來與我的問題完全相同,但我無法得到任何答案爲我工作,即問題仍然存在。

回答

3

提供給action方法的Status實例由MVC的模型聯編程序生成 - 它是一個新的對象,因爲模型聯編程序和NHibernate對彼此一無所知。要使其具有正確的ID,您需要提供該ID作爲表格的一部分(隱藏)。但要小心,以便用戶不能通過發佈比表單包含的字段更多的字段或通過更改隱藏字段的值來進行未經授權的更改。

這是常見的有不同的模型。 MVC在前端使用視圖模型,它具有不同的目的,不一定與您的域模型看起來相同。操作方法負責處理視圖模型中的值,並對域模型執行正確的操作。

+0

啊...好有**是**在我的形式爲ID的隱藏字段,但是標識是一個抽象基類中定義的'protected'場並沒有setter機制。這個想法是任何東西都不應該隨意改變實體的Id值。所以我猜測現在發生的事情是,MVC模型聯編程序無法在它從窗體控件創建的對象上設置Id值。 – 2013-03-06 11:14:11

+0

有時我使用的模式只能在ID尚未設置的情況下進行設置。通常這與'if(_id == 0(或null))類似'throw InvalidOperationException(...);' – 2013-03-06 15:19:13

0

我真的不能添加任何Oskers答案應標記爲正確的。只是幾點。

在你原來的方法Ayende的屬性創建了一個事務,你不需要更新語句,NHibernate的會看到屬性發生變化,並更新它。

如果你覺得第二種方法是去,你可以通過創建一個自定義的模型綁定,這將在NHibernate的目標負載實現這一目標的方式。

見: ASP.NET MVC model binding foreign key relationship

+0

我已經試驗了Jimmy Bogard的自定義模型綁定器,但是我沒有真正使用過它的真實代碼。 http://lostechies.com/jimmybogard/2011/07/07/intelligent-model-binding-with-model-binder-providers/ – 2013-03-04 21:08:35

相關問題