2011-06-07 72 views
5

我有一個類人映射到NHibernate的數據庫。 我從DB加載對象並將其發送給不同的客戶端。 第一個客戶將修改名稱和國家屬性。 第二個客戶端將只修改Name屬性。 然後這兩個返回修改對象到服務器。 當我從第一個客戶端保存數據 - 然後正確保存,名稱和國家都更新。 當我從第二個客戶端保存數據時 - 我遇到問題。它是從第一個客戶的覆蓋數據,並保存國家的新名稱和初始值。我如何告訴NHibernate只保存更改的屬性

我如何告訴NHibernate只保存Name值並且不覆蓋Country值?

public class Person 
{ 
    public string Name { get; set; } 
    public string Country { get; set; } 
} 

public static List<Person> GetEntities() 
{ 
    var factory = CreateSessionFactory(); 
    using (ISession session = factory.OpenSession()) 
    { 
     return session.CreateCriteria<Person>().List<Person>();     
    } 
} 

public static void SaveEntities(List<Person> entities) 
{ 
    var factory = CreateSessionFactory(); 
    using (ISession session = factory.OpenSession()) 
    { 
     using (var t = session.BeginTransaction()) 
     { 
      foreach (var person in entities) 
      { 
       session.Merge(person); 
      } 

      t.Commit(); 
     } 
    } 
} 

P.S:對不起我的英文不好

回答

1

答案是:你不行。 NH不知道只有名字改變了。

您可以通過不允許併發編輯來避免它。例如NH的樂觀鎖定機制。第二個客戶將得到一個StaleObjectStateException

如果兩個客戶端的編輯實際上不在同一時間(但都基於相同的對象狀態),則需要確保第二個客戶端在編輯之前獲取第一個客戶端的更改。例如,通過在打開編輯器之前檢索實際狀態或從服務器發送更改的通知。

如果你想保持併發編輯,你有很多工作要做。客戶需要提供實際改變的信息。那麼你只需要複製這些值。這是艱苦的工作。那麼你可能仍然有這樣的問題,即合併的值不適合。

+0

謝謝Stefan。我可以從第二個客戶端的對象原始狀態發回來檢測對象中的變化,並只保存修改過的屬性。 – gagabu 2011-06-08 10:57:48

+1

重要的是要注意,只有在OP與分離的實體一起工作的情況下,這個答案纔是真實的。如果有人使用從當前會話加載的實體,則NHibernate可以只更新已更改的屬性,方法是在其'class'聲明中啓用'dynamic-update',將這些實體映射爲[由rebelliard](/ a/6271210/1178314) 。 – 2017-05-24 10:09:33

2

這是一個併發問題。第二個客戶端在讀取數據後並不知道數據發生了變化,因此他們的更改會覆蓋第一個客戶端的更改。這可以通過several methods之一在NHibernate中處理,其中最常見的是使用版本列。

這個問題很容易預防,更大的問題是當用戶發生問題時向用戶提供良好的反饋。

+0

我完全同意這點......但這不是問題。問題是如何只保存名稱。 – 2011-06-07 17:52:05

0

傑米井正確地指出,你遇到一個併發的問題,而不是一個映射的問題..

當您創建對象的你NHibernate的映射,無論數據存在於這些對象將是在會話刷新後保存(或更新)到數據庫中。你不能指定單個字段進行更新,它是全部或全部。

只是另一個(不相關)的觀點,你的示例代碼在實體的每個操作中實例化一個新的會話工廠。這通常是一個糟糕的主意,因爲會話工廠的創建成本很高。您最好通過全局上下文(單例)來管理會話工廠,創建一次,並在需要時生成會話(這是較輕的對象)。

12

實際上,你可以告訴NHibernate使用Dynamic Update專門更新「髒」字段。

更多:http://ayende.com/blog/3946/nhibernate-mapping-concurrency

+1

我認爲,雖然其他人正確地敦促原始海報正確理解併發陷阱,但這最接近直接回答他的問題。 – 2011-06-07 20:29:15

+0

我在發帖之前閱讀了這篇文章。但是我無法找到答案來解決我的問題:如何僅從第二個客戶端保存名稱。 – gagabu 2011-06-08 09:41:01

+0

@Matthew:不,這不是問題的答案。動態更新不適用於分離的實體。第二個客戶端將舊數據發送到服務器。您無法知道用戶是否將用戶的名稱設置爲舊名稱。所以它不能通過NH解決,所需的信息缺失。 – 2011-06-10 10:57:19

相關問題