使用 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
如果外部已经存在,则不应启动嵌套事务,为此您可以在开始过程中检查@@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的这篇博客文章中找到示例