当我用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
答案 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
在此博客文章中找到示例