1

我一直试图让这个工作一段时间。

我有一个由另一个开发人员编写的存储过程(我们称之为SPA),它对数据库进行多次插入,所有这些插入都包装在存储过程的事务中。我还有另一个不使用事务的存储过程(调用它SPB)。

从我的 .NET 代码中,我还需要将这两个存储过程包装在一个事务中,以确保如果SPB不成功,则所有内容SPA都回滚。不幸的是,这对我不起作用。我得到的错误是:

无法回滚 SALE。未找到该名称的事务或保存点。
EXECUTE 之后的事务计数表明 BEGIN 和 COMMIT 语句的数量不匹配。先前计数 = 1,当前计数 = 2。

我已经确认ROLLBACK或者COMMIT总是SPA在退出之前被调用。我的 .NET 代码非常简单:

try {
    conn.Open();
    trans = conn.BeginTransaction();
    prod.Connection = conn;
    prod.Transaction = trans;

    // Execute SPA
    // Execute SPB

} catch (Exception ex) {
    trans.Rollback();
} finally {
    conn.Close();
}

如果我将 .NET 排除在外,并简单地使用 SSMS 来包装 SP,那么我会得到相同的错误消息。

BEGIN TRAN
DECLARE @return_value int
EXEC    @return_value = [dbo].[spSPA] [...]
SELECT  'Return Value' = @return_value
COMMIT TRAN

有任何想法吗?

编辑:

SPA看起来像:

BEGIN TRY
BEGIN TRAN SALE

IF SomeCondition
  DoSomething
ELSE
  ROLLBACK TRAN SALE
  RETURN 100

IF SomeCondition
  DoSomething
ELSE
  ROLLBACK TRAN SALE
  RETURN 200

...

COMMIT TRAN SALE
RETURN 0

END TRY
BEGIN CATCH
  IF XACT_STATE() <> 0
    ROLLBACK TRAN SALE
END CATCH
4

1 回答 1

1

我终于发现了我的问题。我收到警告Cannot roll back SALE. No transaction or savepoint of that name was found.是因为如果您有嵌套事务,则在回滚时,您必须指定最外层事务的名称。当然,我不知道那笔交易的名称是什么。

解决方法是使用TechNet上描述的保存点。因此,我必须检查是否存在现有事务,如果有,请使用保存点。否则,创建我自己的:

DECLARE @TRANCOUNT int
SET @TRANCOUNT = @@TRANCOUNT

IF @TRANCOUNT = 0 BEGIN TRAN
ELSE SAVE TRANSACTION SALE
于 2013-11-15T17:25:10.187 回答