我有一个我正在通过C#执行事务调用的sproc:
using (var dbContext = PowerToolsDatabase.GetDataContext())
{
dbContext.Connection.Open();
using (dbContext.Transaction = dbContext.Connection.BeginTransaction(System.Data.IsolationLevel.Serializable))
{
foreach (var element in package.AddOrUpdateElements)
{
dbContext.usp_Element_Commit( /* args */);
}
dbContext.Transaction.Commit();
}
}
在那个sproc中有一个try catch,以及在某些情况下执行的try部分中的RAISERROR
BEGIN TRY
BEGIN TRANSACTION
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
-- Perform Name Uniqueness check (for new)
IF EXISTS ( SELECT PK.identifier --... )
BEGIN
RAISERROR(60000, 16, 1, 'dbo.usp_Element_Commit', 'Supplied Element Name (for new Element) already exists')
RETURN
END
-- Do stuff
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF XACT_STATE() <> 0
BEGIN
ROLLBACK TRANSACTION;
END
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;
SELECT
@ErrorMessage = 'dbo.usp_Element_Commit -- ' + ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE();
RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState);
END CATCH;
当我运行它并在sproc的try部分内点击RAISERROR时,我得到以下多个错误:
dbo.usp_Element_Commit -- Supplied Element Name (for new Element) already exists
Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 1, current count = 0.
Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 1, current count = 0.
在不弄乱外部事务的情况下,建议的处理错误并跳转到catch块的方法是什么?
此外,如果我从sproc中的catch块中删除回滚,那么我得到相同的Transaction Count消息,其中Previous Count = 1,current count = 2
答案 0 :(得分:2)
我使用保存点或事务将我的sproc更改为follow this pattern,具体取决于是否已有现有事务。它现在按预期工作。
BEGIN TRY
declare @trancount int = @@trancount
if @trancount = 0
begin transaction
else
save transaction usp_element_commit_transaction;
set transaction isolation level serializable
-- Perform Name Uniqueness check (for new)
IF EXISTS ( SELECT PK.identifier --... )
BEGIN
RAISERROR(60000, 16, 1, 'dbo.usp_Element_Commit', 'Supplied Element Name (for new Element) already exists')
RETURN
END
-- Do stuff
COMMIT TRANSACTION
END TRY
BEGIN CATCH
declare @xstate int = xact_state()
if @xstate = -1
rollback
else if @xstate = 1 and @trancount = 0
rollback
else if @xstate = 1 and @trancount > 0
rollback transaction usp_element_commit_transaction;
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;
SELECT
@ErrorMessage = 'dbo.usp_Element_Commit -- ' + ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE();
RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState);
END CATCH;