TransactionScope与嵌套事务

时间:2014-07-09 15:05:53

标签: c# transactions

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方法内部?

当它试图在MoveMessageToErrorQueue中创建一个新事务时,我得到一个异常,说明事务已经中止。

更新

如果我使用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方法中的事务失败,我希望能够在最后一个方法中使用相同的根事务。

感谢您的帮助。

更新2

在DTC事务中(以及使用该模式的事务),失败是致命和立即的。一个注定的标志被设置:它被设置。“

这就说明了一切。我认为这种行为是不同的。

2 个答案:

答案 0 :(得分:2)

使用嵌套的TransactionScopes,仍然只有一个事务。嵌套作用域不会创建新事务。交易无法嵌套。 System.Transactions不支持此功能。它也不支持保存点。

当你回滚嵌套的范围时,你会毁掉整个交易。

我不确定如何获得你想要的行为。使用System.Transactions,您必须避免任何事情毁坏当前事务。也许您可以使用SQL Server的保存点来撤消失败的ProcessMessage所具有的影响。或者,您可以为ProcessMessage和MoveMessageToErrorQueue使用不同的数据库连接。

答案 1 :(得分:0)

"在DTC交易(以及使用该模式的交易)中,失败是致命且立竿见影的。一个注定的标志被设置:它被设置。"