2014-07-09 160 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