2009-09-07 35 views
-1

由於NHibernate的ISession的跟蹤變化,我想知道如果我可以拋棄在一個會話中的所有變化,是這樣的:如何恢復NHibernate會話中的所有更改?

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

// Somewhere else... 
var session = sessionFactory.OpenSession(); 
person.Name = "John Doe"; 
using(var tx = session.BeginTransaction) 
{ 
    session.Save(person); 
    tx.Commit(); 
} 

person.Name = "Jane Doe"; 
// Now, can I do something like this? 
session.RevertAll(); 
Assert.AreEqual("John Doe", person.Name); 

回答

4

NH不會恢復您在實體中所做的更改。關注實體的狀態是業務邏輯的責任。

「撤消」更改的最安全方法是:回滾事務,清除(或重新創建)會話並從頭開始。

會話中有重新加載方法。它將數據庫中的狀態重新加載回實體。但是這對這種情況不起作用,因爲NH可能已經刷新了一些變化,例如。在執行查詢之前。 (它可以很好地用於分離的實體。)

+0

是否可以回滾已提交的事務? – Zegar 2013-11-26 15:08:44

+0

@zegar:簡答:不會。長答案:您可以嘗試解決分佈式事務。這是一個數據庫服務器技術(例如來自SQL Server),而不是NHibernate相關的技術。我想知道你爲什麼想這樣做。 – 2013-11-27 07:15:18

1
session.Clear() 

隨着session.Clear,NHibernate會話將不包含任何髒對象了。但是,這並不意味着你的主張會奏效。 NHibernate不會恢復你的對象本身的狀態。 爲了實現這個目標,我們必須自己實現可撤銷支持。 (你可以看看這個IEditableObject接口)。

但是,一旦你保存並提交/刷新了,那麼你的數據庫已經做了修改。 session.Clear不會恢復這些變化。

+1

哦,等等,然後它只是從會話中刪除對象,是嗎? – 2009-09-07 20:17:55

2
session.Refresh(entity); // Cancel object changes, and changes of object collections 

對於取消編輯的所有對象:

var e = ((SessionImpl)session).PersistenceContext.EntityEntries; 
var allEntities = e.Keys.Cast<object>().ToList(); 
foreach (var entity in allEntities) 
     session.Refresh(entity); 
//Maybe it's not a good practice... 
0

嘗試設置會話刷新模式提交。

session.FlushMode = FlushMode.Commit; 

未分離時,數據對象處於「瞬態」或「持續」狀態。

瞬態對象是新對象,當顯式保存時將導致INSERT語句 。 Persisted對象是當會話被刷新時會導致UPDATE語句的對象(即使您沒有在該對象上調用SaveOrUpdate)。

當會話需要將內存中對象容器與數據庫同步時發生刷新。當發生刷新時,如果您對它們調用了SaveOrUpdate,則所有PERSISTED內存中對象(包含內存中的更改)將被刷新。根據會話的「FlushMode」,刷新在各種條件下觸發。

,在這種情況下,對我的作品的解決方案是:

  1. 設置會話FlushMode爲「提交」。

  2. 刪除處理對象的內存中更新的代碼中對'Flush'的所有引用。

  3. 只有在'保存'並且丟棄該會話時,每次會話都會打開1個事務。