c#带sql的嵌套事务

c#带sql的嵌套事务,c#,sql,sql-server,transactions,C#,Sql,Sql Server,Transactions,当我用c#将sth更新到MS SQL 2005数据库时,我想使用嵌套的SQL事务。我尝试了以下代码: try { conn.Open(); cmd.Connection = conn; cmd.Transaction = conn.BeginTransaction(); ////BEGIN TRAN cmd.CommandType = CommandType.StoredProcedure; cmd.CommandText = "storepro

当我用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();
}

如果外部已存在嵌套事务,则不应启动该事务,为此,可以在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
declare@trancount int=@@trancount
如果@trancount=0
开始传输更新传输
更新数据库集xxx=@xxx,其中xxx=@xxx
如果@@rowcount<1或@@error 0--没有更新记录
开始
如果@trancount=0
rollback tran updatetransport/*updatran是事务的名称*/
返回-1——失败
结束
其他的
开始
如果@trancount=0
提交传输更新传输
返回0——成功
结束

SQL Server并没有真正的嵌套事务——或者至少在开发人员假定的情况下是这样的。您可以启动嵌套事务,但它们实际上没有任何影响,因为提交最内部的事务实际上没有任何作用

您根本无法回滚最内部的事务,因为不可能将名称与回滚一起使用,而不使用名称的回滚将对最外部的事务执行回滚

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

你可以在这篇博文中通过

避免嵌套事务找到例子。因为他们不是。我已经编写了很长一段时间了,从来都不需要代码中的嵌套事务。您认为需要一个事务的事实表明您的设计可能是错误的。您的存储过程中已经有一个事务,而c代码中不需要另一个事务。我知道这是多余的,但有时可能有两个人在处理sql和c。同样,当一些想法在逻辑上起作用时,这是非常令人沮丧的,但它并没有像预期的那样发生。无论是对是错,都必须记录在案。
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