我有一个包含3个事务的存储过程,每个事务都在自己的TRY-CATCH
块中,如下所示:
BEGIN TRY
BEGIN TRAN
--SAVE TRAN MySavePoint1
INSERT INTO blah blah blah;
SET @Result1 = @@ROWCOUNT
INSERT INTO blah blah blah;
SET @Result2 = @@ROWCOUNT
UPDATE blah blah blah;
COMMIT TRAN
END TRY
BEGIN CATCH
ROLLBACK TRAN --MySavePoint1
SET @ErrorMessage = ERROR_MESSAGE()
SET @ErrorSeverity = ERROR_SEVERITY()
SET @ErrorState = ERROR_STATE()
RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState)
END CATCH
...以SELECT结尾以返回结果:
SELECT
@Result1 AS Result1,
@Result2 AS Result2,
@Result3 AS Result3,
@Result4 AS Result4,
@Result5 AS Result5,
@Result6 AS Result6
通过以下代码从我的应用程序调用存储过程:
With New DBModel(SqlConnect)
With CType(.Database.Connection, SqlClient.SqlConnection)
AddHandler .InfoMessage, AddressOf InfoMessage
.FireInfoMessageEventOnUserErrors = True
End With
Dim Results As Results = .Database.SqlQuery(Of Results)("MyStoredProcedure").FirstOrDefault
' Code to handle Results here
.Dispose()
End With
以下是问题:
第一笔交易将失败,但另外两笔交易将成功。返回的结果反映出它们已被执行,因为我得到了预期的行数,但是,当我查看数据库时,没有任何工作实际完成。我也从第一次交易失败中得到了一个InfoMessage
事件。
要明确的是,我的问题不在于交易失败......它是故意破坏以测试流程的。
为什么其他交易没有真正完成?
答案 0 :(得分:2)
问题是,如果遵循幸福路径,则有3个独立事务,但如果输入了catch块并执行了ROLLBACK savepoint
,则嵌套事务。 ROLLBACK savepoint
将状态返回到保存点,但保持事务处于打开状态,并且不会减少事务计数。因此,如果第一个try / catch中发生错误,则事务保持打开状态,后续的try / catch块在初始BEGIN TRAN
启动的同一事务上下文中运行。完成所有事务后,事务计数将为非零,并且在会话结束时回滚所有工作。
我不清楚你想要完成什么。具有单独事务的保存点的目的是什么?看起来你希望每个都是全部或全部。