2014-07-09 73 views
1
using System; 
using System.Transactions; 

namespace ConsoleApplication3 
{ 
    public class Program 
    { 
     public static void Main(string[] args) 
     { 
      var trans = new TransactionScope(TransactionScopeOption.RequiresNew); 

      try 
      { 
       if (!ProcessMessage(true)) 
       { 
        MoveMessageToErrorQueue(); 
       } 

       trans.Complete(); 
      } 
      catch (Exception) 
      { 
       trans.Dispose(); 
      } 
     } 

     private static bool ProcessMessage(bool throwError) 
     { 
      //write to database 

      var trans = new TransactionScope(TransactionScopeOption.Required); 

      try 
      { 
       if (throwError) 
        throw new Exception(); 

       trans.Complete(); 

       return true; 
      } 
      catch (Exception) 
      { 
       trans.Dispose(); 
      } 

      return false; 
     } 

     private static void MoveMessageToErrorQueue() 
     { 
      var trans = new TransactionScope(TransactionScopeOption.Required); 

      trans.Complete(); 
     } 
    } 
} 

如何使MoveMessageToErrorQueue方法中的事務範圍在主事務中登記,而不是在ProcessMessage方法中的事務範圍中?嵌套事務的TransactionScope

當它試圖在MoveMessageToErrorQueue內部創建一個新的事務時,我得到一個異常,指出該事務已經被中止。

UPDATE

我得到同樣的結果,如果我用一個CommittableTransaction

using System; 
using System.Transactions; 

namespace ConsoleApplication3 
{ 
    public class Program 
    { 
     public static void Main(string[] args) 
     { 
      using (var trans = new CommittableTransaction()) 
      { 
       try 
       { 
        if (!ProcessMessage(trans, true)) 
        { 
         MoveMessageToErrorQueue(trans); 
        } 

        trans.Commit(); 
       } 
       catch (Exception) 
       { 
        trans.Rollback(); 
       }     
      } 
     } 

     private static bool ProcessMessage(Transaction trans, bool throwError) 
     { 
      //write to database 

      var transScope = new TransactionScope(trans); 

      try 
      { 
       if (throwError) 
        throw new Exception(); 

       transScope.Complete(); 

       return true; 
      } 
      catch (Exception) 
      { 
       transScope.Dispose(); 
      } 

      return false; 
     } 

     private static void MoveMessageToErrorQueue(Transaction trans) 
     { 
      var transScope = new TransactionScope(trans); 

      transScope.Complete(); 
     } 
    } 
} 

基本上,如果在的ProcessMessage方法中的交易失敗我希望能夠仍然使用在同一根事務最後一種方法。

感謝您的任何幫助。

UPDATE 2

「在DTC交易(和使用該圖案的交易),故障是致命的和直接的一個註定標誌被設置:。它被設置」

這說明了一切。我認爲這種行爲是不同的。

+0

看起來更像C# – cup

+0

在原來的情況下,你可以通過複製構造函數將TransScope傳遞給MoveMessageToErrorQueue嗎? – cup

+0

嗨,感謝您的評論,但我沒有關注你。 – Marco

回答

0

「在DTC交易(以及使用該模式的交易)中,失敗是致命的並且是立即的,其中一個註定標誌被設置:它被設置。

+0

你從某處引用了這個嗎?如果是這樣,在哪裏? –

+0

我做了,但我不記得我從哪裏複製它,對不起。 – Marco

2

嵌套TransactionScopes仍然只有一個事務。嵌套作用域不會創建新的事務。事務不能嵌套。 System.Transactions不支持這一點。它也不支持保存點。

當你回滾一個嵌套的作用域時,你會毀掉整個事務。

我不知道如何得到你想要的行爲。有了System.Transactions,你必須避免任何事情來破壞當前的事務。也許你可以使用SQL Server的保存點來撤消失敗的ProcessMessage所具有的效果。或者,您可以爲ProcessMessage和MoveMessageToErrorQueue使用不同的數據庫連接。

+0

我將不得不改變我擁有的東西,因爲我真的認爲我可以處理嵌套事務中的一個,但仍然提交根節點。由於這是不可能的,我可能不得不拆分我的邏輯。感謝您的評論。 – Marco