任务,TransactionScope和SQL Server存储过程

时间:2011-09-06 15:44:24

标签: c# sql-server-2008 stored-procedures task transactionscope

我必须更新一些我以XML格式发送数据的DataTable。如果出现问题,我的存储过程有事务中止操作。但是我必须更新的记录数量非常大,XML达到35 mb +。它只是在开发中,实时数据会更大。

为了处理这个问题,我想通过以块的形式发送数据来更新,也就是说,我将一次发送几百条记录的XML。我尝试使用Task库来并行更新数据库。

var ret=0;
using(var ts = new TransactionScope(TransactionScopeOption.Required,
                                                      new TimeSpan(2,0,0))
{
    try
    {
        for(some condition)
        {
            get chunk of records
            generate xml
            create new task and call routing to push data to db
            var t = create new task and call routing to push data to db
            tasks.Add(t);
        }

        Task.WaitAll(tasks.ToArray());
        ts.Complete();
        foreach(var t in tasks)
            ret += t.Result;
    }
    catch(Exception ex)
    {
        //log exception and show user message
    }
}
return ret;

但我得到的异常是交易已经中止。

我需要做的是在单个事务中完成更新,因为如果任何块无法正确更新,我必须回滚任何更改。

编辑: - 我正在使用Reed Copsey建议的new TransactionScope(TransactionScopeOption.Required,new TimeSpan(2,0,0)),但即使在数据库调用完成2-3秒后仍然出现错误 System.Transactions.TransactionAbortedException: The transaction has aborted. ---> System.TimeoutException: Transaction Timeout

只有一个电话

2 个答案:

答案 0 :(得分:1)

在致电ts.Complete()之前,您需要等到任务完成。这看起来应该更像:

using(var ts = new TransactionScope())
{
    try
    {
        List<Task> tasks = new List<Task>();

        for(some condition)
        {
            // get chunk of records
            // generate xml
            // create new task and call routing to push data to db
            var task = PushDataAsync(theData); // make the task
            tasks.Add(task); // Keep a reference in a collection
        }

        // Wait until all tasks are done, so you can complete the transaction...
        // If any task raises an exception, you'll get an AggregateException here
        Task.WaitAll(tasks.ToArray());

        ts.Complete();
    }
    catch(Exception ex)
    {
        //log exception and show user message
    }
}

答案 1 :(得分:0)

你有没有考虑线程安全?我想知道PushDataAsync里面有什么。

TransactionScope无法跨越开箱即用的线程。它在内部使用线程本地存储。范围属于单个线程的事实在文档中被明确地调用。

不确定您是否真正朝着正确的方向前进,但如果要跨多个线程协调事务,请查看DependentTransaction:http://msdn.microsoft.com/en-us/library/system.transactions.dependenttransaction.aspx