C# TSQL try catch事务错误处理,事务计数不匹配
我有一个从C#调用的存储过程,通过执行以下操作处理事务:C# TSQL try catch事务错误处理,事务计数不匹配,c#,sql-server,tsql,ado.net,transactions,C#,Sql Server,Tsql,Ado.net,Transactions,我有一个从C#调用的存储过程,通过执行以下操作处理事务: using (var dbContext = PowerToolsDatabase.GetDataContext()) { dbContext.Connection.Open(); using (dbContext.Transaction = dbContext.Connection.BeginTransaction(System.Data.IsolationLevel.Serializable)) {
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();
}
}
在该存储过程中,有一个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;
处理错误和跳转到catch块而不破坏外部事务的推荐方法是什么
另外,如果我在存储过程中从catch块中删除回滚,那么我会收到与前一个Count=1、当前Count=2相同的事务计数消息。我将存储过程更改为使用保存点或事务的状态,具体取决于是否已有事务。现在它的工作原理和预期的一样
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;
当出现错误时,您的C#如何跳过提交?@KM从dbContext.usp#u元素#COMMIT调用中抛出SqlException,因此它将跳转到封闭using块中的dispose,该块调用C#上的Rollbacktransaction@JNK一次回滚可以回滚所有内容。而XACT_STATE()0毫无意义。你可以自己试试看。
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;