将事务与任务并行库一起使用 [英] using transaction with task parallel library

查看:30
本文介绍了将事务与任务并行库一起使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有 N 个进程在 SQL Server 2008 上运行.如果任何一个进程失败,我需要回滚所有其他进程.

I have N process to run over SQL Server 2008. If any of the processes fails I need to rollback all the others.

我正在考虑使用 TPL 创建一个父任务和 N 个子任务.所有这些都包含在一个 transactionScope (IsolationLevel.ReadCommitted) 中,但在我下面的示例中,child2 引发错误(customers2 不是有效表)而 child1 不会't 回滚了.

I was thinking to use the TPL creating a parent task and N child task. All of this enclosed with a transactionScope (IsolationLevel.ReadCommitted) but in my example below, the child2 throws an error(customers2 is not a valid table) and the child1 doesn't rolled back.

我在这里假设有什么问题吗?还有其他方法可以管理这种情况吗?

Am I assuming something wrong here? is there other way to manage this scenario?

这是我的测试代码:

编辑我在当前事务上使用 DependClone 修改了如下代码.我认为是有效的.

edit I modified the code as below using the DependClone on the current transaction. I think is working.

try
        {
            using (TransactionScope mainTransaction = TransactionUtils.CreateTransactionScope())
            {
                var parentTransactionClone1 = Transaction.Current.DependentClone(DependentCloneOption.BlockCommitUntilComplete);
                var parentTransactionClone2 = Transaction.Current.DependentClone(DependentCloneOption.BlockCommitUntilComplete);

                var parentTask = Task.Factory.StartNew(() =>
                {
                    var childTask1 = Task.Factory.StartNew(() =>
                    {
                        using (TransactionScope childScope1 = new TransactionScope(parentTransactionClone1))
                        {
                            SqlConnection cnn = new SqlConnection("Server=.\\sqlexpress;Database=northwind;Trusted_Connection=True;");
                            cnn.Open();
                            SqlCommand cmd = new SqlCommand("update customers set city ='valXXX' where customerID= 'ALFKI'", cnn);
                            cmd.ExecuteNonQuery();
                            cnn.Close();
                            childScope1.Complete();
                        }

                        parentTransactionClone1.Complete();

                    }, TaskCreationOptions.AttachedToParent);

                    var childTask2 = Task.Factory.StartNew(() =>
                    {
                        using (TransactionScope childScope2 = new TransactionScope(parentTransactionClone2))
                        {
                            SqlConnection cnn = new SqlConnection("Server=.\\sqlexpress;Database=northwind;Trusted_Connection=True;");
                            cnn.Open();
                            SqlCommand cmd = new SqlCommand("update customers2  set city ='valyyy' where customerID= 'ANATR'", cnn);
                            cmd.ExecuteNonQuery();
                            cnn.Close();

                            childScope2.Complete();
                        }

                        parentTransactionClone2.Complete();

                    }, TaskCreationOptions.AttachedToParent);
                });

                parentTask.Wait();
                mainTransaction.Complete();
            }
        }
        catch (Exception ex)
        {
            // manage ex               
        }
public static TransactionScope CreateTransactionScope()
    {
        var transactionOptions = new TransactionOptions();
        transactionOptions.IsolationLevel = IsolationLevel.ReadCommitted;
        transactionOptions.Timeout = TransactionManager.MaximumTimeout;            
        return new TransactionScope(TransactionScopeOption.Required, transactionOptions);
    }

推荐答案

TransactionScope 类为当前线程设置环境事务(另请参见 Transaction.Current 仅.

The TransactionScope class sets the ambient transaction for the current thread (see also Transaction.Current only.

您至少应该假设每个任务都在单独的线程中运行(尽管这对于 TPL 来说不是必需的).

You should at least assume that each task runs in a separate thread (although that is not a necessity with the TPL).

查看备注部分中的重要"框相关文章 - 如果要在线程之间共享事务,则需要使用 DependentTransaction 类.

Review the "important" box in the remarks section of the relevant article - if you want to share a transaction between threads, you need to use the DependentTransaction class.

就我个人而言,我确信在多个线程之间共享事务的整个工具在技术上是有效的,但是,我一直发现编写每个线程使用单独事务的设计更容易.

Personally, I am sure that the whole facility to share a transaction amongst multiple threads works technically, however, I have always found it easier to write up a design that uses a seperate transaction per thread.

这篇关于将事务与任务并行库一起使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆