我有一個應用程序,我想將幾個數據庫保存到單個事務中。如果它們中的任何一個失敗了,我想把整個事情推回去。但是,我想知道哪些在回滾事務之前失敗(或成功)。內部TransactionScope中的異常導致所有後續的內部TransactionScopes拋出TransactionAbortedException
我有一個內部循環的外部TransactionScope,其中循環的每個迭代都有自己的TransactionScope。我想運行它們並找出哪些失敗。
例如,如果我有5件事我想嘗試並保存,但第一個和第三個將失敗,我想知道這一點。這需要我嘗試所有5次保存,如果失敗了,那麼將所有事情都回滾,但只有在5次嘗試之後。
我看到雖然,第一次失敗的事務後,所有後續使用的TransactionScope立即拋出自己的TransactionAbortedException並不讓我試圖保存,看看它是否工作。
下面是一個例子:
using (var scope = new System.Transactions.TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = System.Transactions.IsolationLevel.RepeatableRead}, EnterpriseServicesInteropOption.Full))
{
var outputStatus = new List<string>();
for (int i = 0 ; i < 5 ; i++)
{
try
{
using (var innerScope = new System.Transactions.TransactionScope(TransactionScopeOption.Required, new TransactionOptions() { IsolationLevel = System.Transactions.IsolationLevel.RepeatableRead}, EnterpriseServicesInteropOption.Full))
{
// Do work here that causes an exception on first iteration only
if (i == 0)
{
throw new Exception(string.Format("Iteration {0} has FAILED", i));
}
else
{
outputStatus.Add("SUCCESS");
}
}
}
catch (Exception e)
{
outputStatus.Add("ERROR, " + e.Message);
}
}
// Print out outputStatus values here
}
在此代碼outputStatus集合看起來像這樣的結尾:
- 錯誤,迭代0失敗
- 錯誤,該交易已中止。
- 錯誤,交易已中止。
- 錯誤,交易已中止。
- 錯誤,交易已中止。
第一個異常後,其餘的都沒有能夠進入成功的語句。
是否有辦法在外部事務範圍內運行所有內部事務並允許我控制外部事務範圍的回滾?
UPDATE:
在實際的代碼,這個樣本模仿我不能更改到包含內部的TransactionScope的代碼。它在一個不受我控制的物體中。所以我正在尋找的解決方案需要能夠處理內部事務拋出異常。
感謝您的回覆。我實際上沒有對內部TransactionScope調用的任何控制。在真實的代碼中(這個例子模仿)控制內部事務範圍的對象是我沒有更新權限的對象。我已經使用該信息更新了我的問題。 – Grandpappy
我看到您的更新,但不會將RequiresNew事務從外部事務中排除,因爲它會創建一個新事務?這將使我無法將所有RequiredNew TransactionScopes回滾,是否正確? – Grandpappy
老實說,我不清楚它會做什麼(我會試試看)。如果您搜索此網站以使用requiredNew,則看起來您是正確的,innerTransaction完全獨立(並且令人困惑)。如果是這種情況,你將不得不自己管理所有的交易,而不是使用使用的代碼塊,而是使用try-catch-finally和靜態Transaction.Current或ctor TransactionScope(TransactionToUse)。請注意,在Dispose被調用之前,沒有任何事情可以完成或撤消。 – Jorge