Get TransactionScope to work with async / await



我正在尝试将async/await集成到我们的服务总线中。我在这个例子的基础上实现了一个SingleThreadSynchronizationContexthttp://blogs.msdn.com/b/pfxteam/archive/2012/01/20/10259049.aspx.

它运行良好,除了一件事:TransactionScope。我在等待TransactionScope里面的东西,它打破了TransactionScope

TransactionScopeasync/await的配合似乎不太好,当然是因为它使用ThreadStaticAttribute将东西存储在线程中。我得到这个例外:

"TransactionScope嵌套不正确&";。

我试图在任务排队之前保存TransactionScope数据,并在运行之前恢复它,但它似乎没有改变任何事情。TransactionScope代码一团糟,所以很难理解其中发生了什么。

有办法让它发挥作用吗?有TransactionScope的替代品吗?

在.NET Framework 4.5.1中,有一组TransactionScope的新构造函数采用TransactionScopeAsyncFlowOption参数。

根据MSDN的说法,它支持跨线程延续的事务流。

我的理解是,这意味着允许你写这样的代码:

// transaction scope
using (var scope = new TransactionScope(... ,
TransactionScopeAsyncFlowOption.Enabled))
{
// connection
using (var connection = new SqlConnection(_connectionString))
{
// open connection asynchronously
await connection.OpenAsync();
using (var command = connection.CreateCommand())
{
command.CommandText = ...;
// run command asynchronously
using (var dataReader = await command.ExecuteReaderAsync())
{
while (dataReader.Read())
{
...
}
}
}
}
scope.Complete();
}

回答有点晚,但我在MVC4上遇到了同样的问题,我通过右键单击项目转到属性将我的项目从4.5更新到4.5.1。选择"应用程序"选项卡将目标框架更改为4.5.1,并按如下方式使用事务。

using (AccountServiceClient client = new AccountServiceClient())
using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
}

您可以使用Transaction.DependentClone()方法创建的DependentTransaction:

static void Main(string[] args)
{
// ...
for (int i = 0; i < 10; i++)
{
var dtx = Transaction.Current.DependentClone(
DependentCloneOption.BlockCommitUntilComplete);
tasks[i] = TestStuff(dtx);
}
//...
}

static async Task TestStuff(DependentTransaction dtx)
{
using (var ts = new TransactionScope(dtx))
{
// do transactional stuff
ts.Complete();
}
dtx.Complete();
}

使用DependentTransaction 管理并发

http://adamprescott.net/2012/10/04/transactionscope-in-multi-threaded-applications/

如果有人仍然关注这个线程。。。

Microsoft.Data.SqlClient v3.0.1似乎修复了.NET Framework异步/等待函数中System.Transactions的死锁问题!我用的是4.8。我使用了显式分布式事务方法,允许通过使用多个连接对单个sql server执行并行查询,但我相信TransactionScope的行为也更好。

创建CommittableTransaction,创建任意数量的SqlConnections,这些SqlConnections登记从父可提交文件创建的DependentTransaction,并行执行连接上的查询,在执行查询后完成依赖项,然后提交/回滚父可提交文件。

我在3个不同的连接上对同一个数据库进行了3次并行异步插入测试。当父级提交正在进行时,我使用了一个消息框来提示提交或回滚。当分布式事务处于活动状态时,表被锁定。我无法在ssms中进行选择。选择提交或回滚后,两者都按预期工作。

上周使用Microsoft.Data.SqlClient 3.0.0时,这是不可能的,因为.Commit()方法会在异步函数中死锁。我甚至用各种方法尝试了BeginCommit/EndCommit。甚至在异步函数中登记依赖项时也出现了问题,但这也得到了解决。现在,最简单的显式分布式事务方法使用async/await。

最新更新