【问题标题】:Is it possible to commit/rollback SqlTransaction in asynchronous?是否可以异步提交/回滚 SqlTransaction?
【发布时间】:2015-07-01 05:10:21
【问题描述】:

我正在尝试异步提交/回滚SqlTransaction。但看起来不支持异步。有什么方法可以让它异步而不使用原始 SQL 来启动事务?

【问题讨论】:

  • @MickyDuncan 感谢您提供的信息。但这不是我要找的。我正在寻找避免 C# 端的线程阻塞。
  • 您是否也在寻找 TransactionScope?它具有处理异步的功能。
  • @MicaëlFélix 谢谢。但我不再使用 .NET。

标签: c# sql-server


【解决方案1】:

使用 .Net Core 3.0,现在理论上可以异步提交或回滚事务,任何事务都来自 DbTransactionSqlTransaction 也是如此。

.Net Core issue #35012。 (或DbTransaction documentation。)

但更重要的是,SqlTransaction 底层实现尚未利用它:您可以在其上调用异步方法,但目前据我在 source code 中看到的,它们仍在委派同步同行通过DbTransaction default implementationMicrosoft.Data.SqlClient 也是这种情况(没有异步覆盖)。

因此,您可以使用 .Net Core 3.0 使您的代码准备好以异步方式提交或回滚,但您将不得不等待更多时间才能使它们真正异步。

【讨论】:

    【解决方案2】:

    看起来不像。翻看相关代码,其他所有方法都是异步直通的(同步版本是特例),而SqlTransaction和其他相关代码只是同步的。对于重叠的部分,SqlTransaction 只是同步等待任务完成(例如在处理重新连接时)。

    事实上,随着您深入了解代码,事务操作明确禁止任何异步操作,因此不包括异步事务操作似乎是设计使然。如果您确实找到了解决方法,请记住这一点 - 系统并非设计为允许并发操作,因此始终在您收到(任何)任务后立即使用 await

    如果你想解决这个问题,你必须一直深入到直接为 SQL Server 创建二进制消息(或者至少使用反射来执行一些内部帮助方法),这是行不通的太容易了(当然,这需要您访问SqlConnection 使用的内部 TCP 连接 - 并处理重新连接等)。

    查看 EntityFramework 代码,他们的解决方案非常简单 - 他们只需调用 Commit。这并不像听起来那么疯狂 - 首当其冲的工作是在 ExecuteXXXAsync 方法本身中完成的,Commit 是“免费的” - 它只会花费您与服务器的通信,而这通常不是太贵了。

    考虑到这些限制,您的性能仍然不应该受到明显影响 - 如果您有几个并发 Commits,您的线程池可能不得不分配一个或两个线程,而不是通常的数量,但替代方案很多更痛苦。

    【讨论】:

    • 感谢您的精彩回答!
    • 略过:因为 T-SQL 有用于事务管理的命令 (SET TRANSACTION ISOLATION LEVEL / BEGIN TRANSACTION / ROLLBACK / COMMIT) 你并不真的需要一路下降到TDS的水平。我仍然不建议在这方面覆盖设计者,但您可以制作一个异步发出 SQL 语句的包装器来管理事务。不过,这对于不知道您已经开始事务的代码可能没有必要很好地发挥作用。
    【解决方案3】:
    using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
    {
        . . .
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-13
      • 2016-06-16
      • 2012-03-15
      • 2014-09-15
      • 1970-01-01
      相关资源
      最近更新 更多