TransactionScope
和SQL Server都不支持嵌套事務。
您可以嵌套TransactionScope
實例,但只具有嵌套事務的外觀。實際上,有一種叫做「環境」交易的東西,一次只能有一件。環境交易的交易取決於您在創建範圍時使用的TransactionScopeOption
的內容。
爲了更詳細地解釋,考慮以下因素:
using (var outer = new TransactionScope())
{
DoOuterWork();
using (var inner1 = new TransactionScope(TransactionScopeOption.Suppress))
{
DoWork1();
inner1.Complete();
}
using (var inner2 = new TransactionScope(TransactionScopeOption.RequiresNew))
{
DoWork2();
inner2.Complete();
}
using (var inner3 = new TransactionScope(TransactionScopeOption.Required))
{
DoWork3();
inner3.Complete();
}
outer.Complete();
}
下面是每個內部範圍的會發生什麼:
inner1
在一個隱含的事務執行,獨立的outer
。保證在DoWork1
中發生的任何事情都是原子的。如果這個過程中途失敗,你將會有不一致的數據。無論outer
發生了什麼,任何在這裏發生的工作都會一直承諾。
inner2
在新事務中執行,獨立於outer
。這是一個不同的交易從outer
但它是不是嵌套。如果失敗了,在outer
(DoOuterWork()
)發生的工作和任何其他範圍仍然可以提交,但這裏的難題是:如果它完成,然後回滾整個outer
交易將不回滾所做的工作在inner2
之內。這就是爲什麼它沒有真正嵌套。另外,inner2
將無法訪問由outer
鎖定的任何行,因此如果您不小心,最終可能會導致死鎖。
inner3
在執行相同交易爲outer
。這是默認行爲。如果DoWork3()
失敗且inner3
永不完成,則整個事務回滾。同樣,如果inner3
成功完成,但回滾outer
,則在DoWork3()
中完成的任何工作也將回滾。
所以你可以希望看到這些選項都沒有實際嵌套,並且不會給你你想要的。 Required
選項近似於嵌套事務,但不能讓您獨立提交或回滾事務內的特定工作單元。
您可以在SQL Server中最真實的嵌套事務是SAVE TRAN
語句與一些TRY/CATCH
塊相結合。如果你可以把你的邏輯放在一個或多個存儲過程中,這將是一個不錯的選擇。
否則,根據Oded的建議,您需要爲每張發票使用單獨的交易。
+1 - 保存點是完美的選擇 – 2010-05-08 23:58:27