【问题标题】:How do I enable nested transactions with ADO.NET and SQL Server?如何使用 ADO.NET 和 SQL Server 启用嵌套事务?
【发布时间】:2010-05-18 11:34:23
【问题描述】:

我对@9​​87654321@ 有类似的问题。我如何允许嵌套事务而不是检查?

我正在使用带有 ADO.NET 的 Microsoft SQL Server 数据库。我已经看到使用 T-SQL 的示例以及使用 begin 和使用事务名​​称启动事务的示例。调用 connection.BeginTransaction 时,我在同一个连接中调用了另一个函数,它再次调用 BeginTransaction,这给了我异常:

SqlConnection does not support parallel transactions.

似乎许多 Microsoft 变体都允许这样做,但我不知道如何使用我的 .mdf 文件来执行此操作。

如何允许使用 C# 和 ADO.NET 与 Microsoft SQL Server 数据库进行嵌套事务?

【问题讨论】:

    标签: c# sql-server ado.net nested-transactions


    【解决方案1】:

    SQL Server 整体不支持嵌套事务。在 T-SQL 中,您可以在较早的 BEGIN TRAN 中发出 BEGIN TRAN,但这只是为了方便。只有外部交易才重要。 SQL Server 的 .NET 客户端 (SqlConnection) 甚至不允许您这样做,并在您尝试时抛出此异常。

    【讨论】:

    • 我的主人说他们提供“Microsoft SQL 2008”。这是 T-SQL 吗?如果不是,T-SQL 来自哪里?我只想计算外部交易。 'Microsoft SQL 2008' 不允许这样做吗? (也许配置它不抛出异常?)
    • T-SQL 是 Microsoft 的 SQL 标准变体,可在所有 SQL Server 版本中运行。如果您想避免此异常,只需在提交或回滚较早的事务之前避免调用BeginTransaction - 如果较早的事务仍处于挂起状态,您就不能成为事务。我建议你看看使用 TransactionScope (msdn.microsoft.com/en-us/library/…) 而不是自己管理它们。
    • 嗯,这不是一回事。此代码与 sqlite 一起使用,我不确定它是否支持(可能是因为它似乎支持所有 ado.net)。但这听起来很奇怪,如果 T-SQL 在所有版本的 sql server 中,那么我不应该拥有它并且不应该允许这样做吗?这一功能将使我的生活更轻松。即使只有一个函数使用它(我想我可以销毁它,因为它只在初始化时只使用一个连接直到完成。)
    • T-SQL 是 SQL Server 的 SQL 语言方言。 SqlConnection 在 T-SQL 中向 SQL Server 发出命令,但即使 T-SQL 允许您(表面上)嵌套事务,SqlConnection 确实不允许允许它。您可以通过 SqlCommand 自己发出 BEGIN TRAN 命令,但随后您将绕过所有 .NET 对事务的支持。
    • 嗯。很高兴知道。谢谢,看起来解决这个问题的最简单方法是杀死外部事务,因为它只使用一次,并且可以在 sqlite 中获得更好的性能(它只运行一次,所以它没有太大的提升)。
    【解决方案2】:

    SQL Server 支持嵌套事务是一个常见的误解。它不是。打开多个事务然后调用 commit 绝对没有任何作用。您可以轻松编写一些测试 SQL 来自己尝试。此处模拟嵌套事务的唯一选择是使用保存点。

    我应该补充一点,唯一重要的是当@@TRAN_COUNT 达到零时,只有外部事务将被提交。

    【讨论】:

      【解决方案3】:
      SqlConnection conn = new SqlConnection(@"Data Source=test;Initial Catalog=test;User ID=usr;Password=pass");
      conn.Open();
      var com = conn.CreateCommand();
      
      com.CommandText = "BEGIN TRANSACTION";
      com.ExecuteNonQuery();
      com.CommandText = "BEGIN TRANSACTION";
      com.ExecuteNonQuery();
      com.CommandText = "INSERT INTO testTable (ParamName,ParamValue) values ('test','test');";
      com.ExecuteNonQuery();
      com.CommandText = "COMMIT TRANSACTION";
      com.ExecuteNonQuery();
      com.CommandText = "ROlLBACK TRANSACTION";
      com.ExecuteNonQuery();
      
      com.CommandText = "SELECT COUNT(*) FROM testTable ";
      
      MessageBox.Show(string.Format("Found {0} rows.", com.ExecuteScalar()));
      

      【讨论】:

      • 这个答案可能会受益于一些关于您通过运行它所发现的内容。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-26
      • 1970-01-01
      相关资源
      最近更新 更多