2009-07-28 47 views
17

能做些什麼NHibernate的嵌套事務,以及如何實現它們?我正在使用SQL Server 2008,所以支持絕對在DBMS中。如何在NHibernate中嵌套事務?

我覺得,如果我嘗試這樣:

using (var outerTX = UnitOfWork.Current.BeginTransaction()) 
{ 
    using (var nestedTX = UnitOfWork.Current.BeginTransaction()) 
    { 
     ... do stuff 
     nestedTX.Commit(); 
    } 

    outerTX.Commit(); 
} 

那麼到時候談到outerTX.Commit()交易已經變得不活躍,並導致在會話AdoTransaction一個的ObjectDisposedException。

難道我們因此應該代替創建嵌套NHibernate的會議?還是有一些其他類應該用來包裝事務(我聽說過TransactionScope,但我不確定那是什麼)?

現在,我使用Ayende's UnitOfWork implementation(感謝Sneal)。

原諒在這個問題上任何的幼稚,我還是新來的NHibernate。

謝謝!

編輯:我發現,你可以使用的TransactionScope,如:

using (var transactionScope = new TransactionScope()) 
{ 
    using (var tx = UnitOfWork.Current.BeginTransaction()) 
    { 
     ... do stuff 
     tx.Commit(); 
    } 

    using (var tx = UnitOfWork.Current.BeginTransaction()) 
    { 
     ... do stuff 
     tx.Commit(); 
    } 

    transactionScope.Commit(); 
} 

但是我沒有那麼興奮,這一點,因爲它鎖定在我們使用SQL Server和我也發現,如果數據庫是遠程的,那麼你不得不擔心MSDTC已啓用......另外一個組件出錯了。嵌套事務在SQL中非常有用且容易實現,我認爲NHibernate會採用某種方式來模擬相同的...

+1

你已經能夠找到答案?如何最終做嵌套事務? – learning 2010-07-20 10:23:58

+0

@ user281180,有點。我找不到真正做到的方法,但你可以近似體驗。在這裏發表了博客:http://blog.constructionhive.com/2010/07/22/nested-transactions-and-nhibernate/ – Gavin 2010-07-22 00:19:12

回答

1

如果要嵌套使用Ayende's UnitOfWork implementation,那麼該實現不支持嵌套。您正在使用的實現(至少對於Web應用程序)的另一個問題是它在靜態變量中佔用ISession實例。

我昨天改寫了我們的UnitOfWork由於這些原因,它最初是基於關閉加百列的。

我們不使用UnitOfWork.Current.BeginTransaction(),我們使用UnitofWork.TransactionalFlush(),它在最後創建一個單獨的事務以一次刷新所有更改。

using (var uow = UnitOfWork.Start()) 
{ 
    var entity = repository.Get(1); 
    entity.Name = "Sneal"; 
    uow.TransactionalFlush(); 
} 
+0

是的,我覺得我應該從一開始就使用Rhino Commons ...我認爲我和Gabriel一起去了,所以我可以從頭開始構建單元工作模式(它確實幫助我理解了很多),但現在是時候和大男孩們一起玩了......感謝。 – Gavin 2009-07-28 16:34:28

2

我一直在努力與此一段時間了。我們會有另一個裂縫。

我想實現個性化服務容器的交易 - 因爲這使他們自成一體 - 但是能夠巢一堆更大事務中的服務方法,如果需要回滾一大堆。

因爲我正在使用Rhino Commons我現在要嘗試使用With.Transaction方法進行重構。基本上,它允許我們編寫代碼,就好像事務是嵌套的,儘管實際上只有一個。

例如:

private Project CreateProject(string name) 
{ 
    var project = new Project(name); 
    With.Transaction(delegate 
    { 
     UnitOfWork.CurrentSession.Save(project); 
    }); 
    return project; 
} 

private Sample CreateSample(Project project, string code) 
{ 
    var sample = new Sample(project, code); 
    With.Transaction(delegate 
    { 
     UnitOfWork.CurrentSession.Save(sample); 
    }); 
    return sample; 
} 

private void Test_NoNestedTransaction() 
{ 
    var project = CreateProject("Project 1"); 
} 

private void TestNestedTransaction() 
{ 
    using (var tx = UnitOfWork.Current.BeginTransaction()) 
    { 
     try 
     { 
      var project = CreateProject("Project 6"); 
      var sample = CreateSample(project, "SAMPLE006", true); 
     } 
     catch 
     { 
      tx.Rollback(); 
      throw; 
     } 
     tx.Commit(); 
    } 
} 

Test_NoNestedTransaction(),我們正在創建一個單獨的項目,沒有一個更大的交易的情況下。在這種情況下,在CreateSample中將創建並提交新的事務,或者在發生異常時回滾。

Test_NestedTransaction()中,我們創建了一個樣本和一個項目。如果出現任何問題,我們希望兩者都回滾。實際上,CreateSampleCreateProject中的代碼將運行,就好像根本沒有交易一樣;完全是外部事務決定是否回滾或提交,並根據是否拋出異常來完成。真的那就是爲什麼我要爲外部事務使用手動創建的事務;所以我們可以控制是否提交或回滾,而不僅僅是默認爲on-exception-rollback-else-commit

你可以通過把一大堆這樣的事情,通過代碼實現無Rhino.Commons同樣的事情:

if (!UnitOfWork.Current.IsInActiveTransaction) 
{ 
    tx = UnitOfWork.Current.BeginTransaction(); 
} 

_auditRepository.SaveNew(auditEvent); 
if (tx != null) 
{ 
    tx.Commit(); 
} 

...等等。但With.Transaction,儘管需要創建匿名代表的笨拙,這很方便。

這種方法相對於使用TransactionScope(除了依賴MSDTC)的一個優點是,在最終的外部事務提交中應該只有一個數據庫刷新,無論有多少方法被調用在兩者之間。換句話說,我們不需要將未提交的數據寫入數據庫,因爲我們總是將它寫入本地NHibernate緩存。

簡而言之,此解決方案不提供對您的交易的最終控制,因爲它不會使用多個交易。我想我可以接受,因爲無論如何,嵌套事務並不是每個DBMS都支持的。但是現在也許我至少可以編寫代碼而不必擔心我們是否已經處於交易中。

13

NHibernate會話不支持嵌套事務。

下面的測試總是在2.1.2版本真:

var session = sessionFactory.Open(); 
var tx1 = session.BeginTransaction(); 
var tx2 = session.BeginTransaction(); 
Assert.AreEqual(tx1, tx2); 

你需要將其包裝在一個TransactionScope支持嵌套事務。

MSDTC必須啓用或者你會得到錯誤:

{"Network access for Distributed Transaction Manager (MSDTC) has been disabled. Please enable DTC for network access in the security configuration for MSDTC using the Component Services Administrative tool."}

2

由於薩蒂什建議,嵌套事務不NHibernate的支持。我還沒有遇到需要嵌套事務的場景,但當然我遇到了一些問題,如果其他工作單元中的其他人已經處於活動狀態,我必須忽略創建事務。

下面的博客鏈接提供了NHibernate的一個例子實施,也應該適用於SQL服務器: http://rajputyh.blogspot.com/2011/02/nested-transaction-handling-with.html