c#与sql嵌套的事务

时间:2015-06-11 08:40:07

标签: c# sql sql-server transactions

当我用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中放入一些数据。如果我输入的数据是正确的,它可以Sussessfully运行。但如果不是,它会捕获以下错误,这与我预期的完全不同,即:

  

[System.Data.SqlClient.SqlException] = {“无法回滚updatetransport。找不到该名称的事务或保存点。\ r \ n执行计数后,EXECUTE表示缺少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

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

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

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

您可以通过Paul Randal

在此博客文章中找到示例