使用 SQL 的 C# 嵌套事务

本文关键字:嵌套事务 SQL 使用 | 更新日期: 2023-09-27 17:55:23

当我使用 c# 将 sth 更新到 MS SQL 2005 数据库时,我想使用嵌套的 sql 事务。我尝试了以下代码:

try
{
    conn.Open();
    cmd.Connection = conn;
    cmd.Transaction = conn.BeginTransaction();
    ////BEGIN TRAN
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.CommandText = "storeprocname";
    cmd.Parameters.Add("@xxx", SqlDbType.VarChar, 50);
    cmd.Parameters["@xxx"].Value = "string_value";
    cmd.ExecuteNonQuery();
    if (<sql can do>)
    {
        cmd.Transaction.Commit();
    }
    else
    {
        cmd.Transaction.Rollback();
    }
}
catch (Exception ex)
{
    cmd.Transaction.Rollback();
}

上面的代码打开一个事务并将一些数据放入sql中。如果我输入的数据正确,它可以成功运行。但如果不是,它会捕获以下错误,这与我的预期完全不同,即:

[System.Data.SqlClient.SqlException] = {"无法回滚更新传输。未找到该名称的事务或保存点。''r'执行后的事务计数指示缺少提交或回滚事务语句。以前的计数 = 1,当前计数 = 2。

代码是SQL的:

begin tran updatetransport
update db set xxx=@xxx  where xxx=@xxx
if @@rowcount < 1 or @@error <> 0 -- no record updated  
begin
    rollback tran updatetransport /*updatran is the name of transaction*/
 return -1 --fail
    end  
   else
begin  
 commit tran updatetransport
 return 0 --success  
end

似乎sql服务器会自动回滚事务。并在我尝试回滚时抛出错误。但是,当我尝试以以下方式修改代码时,仍然没有运气。我错过了什么吗?我在开始交易后刚刚宣布@tcount =@@TRANCOUNT

 if @tcount = @@TRANCOUNT
 begin
    rollback tran updatetransport
 end

使用 SQL 的 C# 嵌套事务

如果外部已经存在,则不应启动嵌套事务,为此您可以在开始过程中检查@@trancount变量,最后:

declare @trancount int = @@trancount
if @trancount = 0 
  begin tran updatetransport
update db set xxx=@xxx  where xxx=@xxx
if @@rowcount < 1 or @@error <> 0 -- no record updated  
begin
    if @trancount = 0 
      rollback tran updatetransport /*updatran is the name of transaction*/
 return -1 --fail
    end  
   else
begin  
  if @trancount = 0 
   commit tran updatetransport
 return 0 --success  
end

SQL Server并没有真正的嵌套事务 - 或者至少以开发人员假设的方式。您可以启动嵌套事务,但它们实际上没有任何影响,因为提交最内层的事务实际上不会执行任何操作。

您根本无法回滚最里面的事务,因为不可能将名称与回滚

一起使用,而没有名称的回滚会对最外层的事务进行回滚。

您可以在Paul Randal的这篇博客文章中找到示例