【问题标题】:c# nested transaction with sqlc# 用sql嵌套事务
【发布时间】:2015-08-26 20:24:21
【问题描述】:

当我用 c# 更新 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] = {"无法回滚 updatetransport。找不到该名称的事务或保存点。\r\nEXECUTE 后的事务计数表明缺少 COMMIT 或 ROLLBACK TRANSACTION 语句。以前的计数= 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 server 正在自动回滚事务。当我试图回滚它时抛出错误。但是,当我尝试按以下方式修改代码时,仍然没有运气。我错过了什么吗? 我在开始交易后声明了@tcount =@@TRANCOUNT

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

【问题讨论】:

  • 避免嵌套事务。因为他们不是。我已经编码了很长时间,并且从不需要代码中的嵌套事务。你认为你需要一个这一事实表明你的设计可能是错误的。
  • 您的存储过程中已经有一个事务,在c#代码中不需要另一个。
  • 我明白这是多余的,但有时可能有两个人处理sql和c#。在某些想法在逻辑上可行的情况下,这也令人沮丧,但它的发生并不像预期的那样。对与错必须记录在案。

标签: c# sql sql-server transactions


【解决方案1】:

如果外部已经存在嵌套事务,则不应启动嵌套事务,为此,您可以在开始过程和最后检查@@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

【讨论】:

    【解决方案2】:

    SQL Server 并没有真正的嵌套事务——或者至少以开发人员所假设的方式。您可以启动嵌套事务,但它们实际上并没有任何影响,因为提交最里面的事务实际上并没有做任何事情。

    您根本无法回滚最里面的事务,因为不可能使用带有回滚名称的名称,而没有名称的回滚会对最外面的事务进行回滚。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-18
      • 2016-08-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多