我必须更新一些我以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
。
只有一个电话
答案 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