2010-04-30 40 views
26

我想嵌套TransactionScopes(.net 4.0),因爲你會在SQL Server中嵌套事務,但它看起來像他們運作不同。我希望我的子事務能夠在它們失敗時回滾,但允許父事務決定是否提交/回滾整個操作。問題是第一次完成時,事務回滾。我意識到完成不同於承諾。嵌套/子TransactionScope回滾

A的什麼,我試圖做的大大簡化例子:

static void Main(string[] args) 
{ 
    using(var scope = new TransactionScope()) // Trn A 
    { 
     // Insert Data A 

     DoWork(true); 
     DoWork(false); 

     // Rollback or Commit 
    } 
} 

// This class is a few layers down 
static void DoWork(bool fail) 
{ 
    using(var scope = new TransactionScope()) // Trn B 
    { 
     // Update Data A 

     if(!fail) 
     { 
      scope.Complete(); 
     } 
    } 
} 

如果我使用這些選項我不能使用抑制或RequiresNew選項Trn鍵乙依賴於Trn鍵A.插入數據,Trn B被Trn A阻止。

任何想法如何讓它工作,或者甚至可以使用System.Transactions命名空間?

感謝

回答

46

你可能不會喜歡這個答案,但是......

投票嵌套範圍

內雖然嵌套的範圍可以加入環境事務的根作用域,在嵌套作用域中調用完成對根作用域沒有影響。只有從根範圍到最後一個嵌套範圍的所有範圍投票才能提交事務,纔會提交事務。

(從Implementing an Implicit Transaction using Transaction Scope

TransactionScope類可惜不用於分揀工作單位提供任何機制(據我所知)。這是全部或沒有。您可以通過使用TransactionScopeOption.Suppress來防止任何事務在特定的工作單元上發生,但這可能不是您想要的,因爲您將失去該範圍內的任何內容的原子性。

當您使用TransactionScope時,只有一個「環境」交易。一旦TransactionScope被處置或收集而沒有執行Complete,則整個環境事務被回滾;就是這樣,遊戲結束了。

事實上,SQL Server不都支持真正的嵌套事務,雖然它可能的(雖然有點不直觀),以實現與適當使用SAVE TRAN報表相同的最終結果。如果您需要這種特殊行爲,將這一邏輯重新實現爲存儲過程(或其中幾個)可能是您的最佳選擇。

+0

謝謝你,我很害怕這樣的答案。 – 2010-06-10 05:05:22

+0

我沒有得到它:爲什麼答案令人失望? Robert希望任何內部範圍都能夠回滾,而只有最外層的才能夠提交。一個簡單的解決方案是:在每個作用域中,如果不想回滾,請調用complete()。那麼最外層的範圍可以選擇提交,只有當所有內層人員都選擇不回滾時。 – Alireza 2013-02-16 10:57:56

+3

@Alireza:OP想要選擇性地提交某些內部事務,同時回滾所有未明確提交的* else *。你的「簡單的解決方案」就是'TransactionScope'的工作方式,並且被記錄爲可以工作,並且被這個答案清楚地解釋,但是如果外部範圍沒有完成,它實際上不會提交在任何內部範圍中所做的更改。這根本不可能使用'System.Transactions'。 – Aaronaught 2013-02-16 16:43:03