在我存储的特效中,我使用Try-Catch,并在Catch块中调用一个错误处理过程,该过程会将错误详细信息记录在ErrorLog表中,然后重新抛出错误。SQL如何; Try-Catch错误信息到错误日志表,用于在事务内执行的存储过程?
在我的C#代码,我使用我的执行存储过程:
using(TransactionScope scope = new TransactionScope()) {
// execute stored procs
scope.Complete();
}
我遇到的问题,如果交易被中止(scope.Complete不会被调用),我的错误处理存储过程会重新抛出sql错误,但不能将错误记录到ErrorLog表中,因为它位于Transaction的上下文中;有没有办法解决 !?我已经知道当事务处于不可提交状态时无法插入数据,那么如何退出事务并仍记录错误?
TSQL代码:
BEGIN PROCEDURE [dbo].[usp_UpsertSomething]
@SomethingID BIGINT
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
-- do something
END TRY
BEGIN CATCH
EXEC dbo.cp_RethrowError
RETURN -1
END CATCH;
END
CREATE PROCEDURE [dbo].[usp_RethrowError]
@ErrorLogID [INT] = 0 OUTPUT -- Contains the ErrorLogID of the row inserted
-- by cp_RethrowError in the ErrorLog table.
AS
BEGIN
-- Return if there is no error information to retrieve.
IF ERROR_NUMBER() IS NULL
RETURN;
DECLARE
@ErrorMessage VARCHAR(4000),
@FormattedErrorMessage VARCHAR(4000),
@ErrorNumber INT,
@ErrorSeverity INT,
@ErrorState INT,
@ErrorLine INT,
@ErrorProcedure VARCHAR(200);
-- Assign variables to error-handling functions that
-- capture information for RAISERROR.
SELECT
@ErrorNumber = ERROR_NUMBER(),
@ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE(),
@ErrorLine = ERROR_LINE(),
@ErrorProcedure = ISNULL(ERROR_PROCEDURE(), '-');
-- Build the message string that will contain original
-- error information.
SELECT @FormattedErrorMessage =
'ErrorLogID %d, Error %d, Level %d, State %d, Procedure %s, ' +
'Line %d, Message: '+ @ErrorMessage;
BEGIN TRY
-- Data insertion/modification is not allowed when
-- a transaction is in an uncommittable state.
IF XACT_STATE() = -1 BEGIN
SET @ErrorLogID = 0;
END
ELSE BEGIN
INSERT [dbo].[ErrorLog]
(
ErrorNumber,
ErrorSeverity,
ErrorState,
ErrorProcedure,
ErrorLine,
ErrorMessage
)
VALUES
(
@ErrorNumber,
@ErrorSeverity,
@ErrorState,
@ErrorProcedure,
@ErrorLine,
@ErrorMessage
);
-- Pass back the ErrorLogID of the row inserted
SELECT @ErrorLogID = @@IDENTITY;
END
END TRY
BEGIN CATCH
PRINT 'An error occurred in stored procedure cp_RethrowError.';
END CATCH
-- Raise an error: msg_str parameter of RAISERROR will contain
-- the original error information.
RAISERROR
(
@FormattedErrorMessage,
@ErrorSeverity,
1,
@ErrorLogID, -- parameter: ErrorLogID in ErrorLog table.
@ErrorNumber, -- parameter: original error number.
@ErrorSeverity, -- parameter: original error severity.
@ErrorState, -- parameter: original error state.
@ErrorProcedure, -- parameter: original error procedure name.
@ErrorLine -- parameter: original error line number.
);
END