Im trying to execute the following query from a console application.
CREATE PROCEDURE main.usp_setup
AS
SET TRANSACTION ISOLATION LEVEL
REPEATABLE READ
BEGIN TRANSACTION
BEGIN
BEGIN TRY
EXEC main.usp_importXml[C:\Users\User\Desktop\people.xml];
END TRY
BEGIN CATCH
INSERT INTO main.errorLog(EntryTime,ErrorNumber,ErrorMessage,ErrorProcedure,ErrorLineNumber,ErrorSeverity,ErrorState)
VALUES (CURRENT_TIMESTAMP,ERROR_NUMBER(),'Failed to import XML',ERROR_PROCEDURE(),ERROR_LINE(),ERROR_SEVERITY(),ERROR_STATE())
declare @message nvarchar(45);
set @message = 'Failed at Import XML - ' + CAST(SCOPE_IDENTITY()AS NVARCHAR(32)) ;
THROW 50001,@message , 20;
END CATCH
BEGIN TRY
EXEC main.usp_afterimport;
END TRY
BEGIN CATCH
INSERT INTO main.errorLog(EntryTime,ErrorNumber,ErrorMessage,ErrorProcedure,ErrorLineNumber,ErrorSeverity,ErrorState)
VALUES (CURRENT_TIMESTAMP,ERROR_NUMBER(),'Failed to Populate',ERROR_PROCEDURE(),ERROR_LINE(),ERROR_SEVERITY(),ERROR_STATE())
set @message = 'Failed to Populate' + CAST(SCOPE_IDENTITY()AS NVARCHAR(32)) ;
THROW 50001,@message , 20;
END CATCH
COMMIT
END
GO
Code in Console Application :
SqlConnection conn = new SqlConnection();
conn.ConnectionString =
"Data Source=DELLC;" +
"Initial Catalog=hr;" +
"User id=geordey;" +
"Password=1234;";
conn.Open();
SqlCommand cmd = new SqlCommand("main.usp_setup", conn);
cmd.CommandType = System.Data.CommandType.StoredProcedure;
int a = cmd.ExecuteNonQuery();
if(a==-1)
{
Console.WriteLine("Error");
}
else
{
Console.WriteLine("Loaded");
}
But when executed the following error is given:
System.Data.SqlClient.SqlException: 'The current transaction cannot be committed and cannot support operations that write to the log file. Roll back the transaction.
Uncommittable transaction is detected at the end of the batch. The transaction is rolled back.'
BEGIN TRANSACTION
BEGIN TRY
EXEC main.usp_importXml[C:\Users\User\Desktop\people.xml];
BND TRY
BEGIN CATCH
INSERT INTO ...
END CATCH
COMMIT
You absolutely cannot do this. Inside a CATCH block you must check for the XACT_STATE()
value and act accordingly:
- 1 The current request has an active user transaction. The request can perform any actions, including writing data and committing the transaction.
- 0 There is no active user transaction for the current request.
- -1 The current request has an active user transaction, but an error has occurred that has caused the transaction to be classified as an uncommittable transaction.
Not only that, but you cannot place the COMMIT after the CATCH. If the transaction has rolled back, what are you going to commit? You should place the COMMIT before the CATCH, and you can have only one TRY/CATCH block, not two.
If you want a good pattern to model after, read Exception handling and nested transactions :
begin
set nocount on;
declare @trancount int;
set @trancount = @@trancount;
begin try
if @trancount = 0
begin transaction
else
save transaction usp_my_procedure_name;
-- Do the actual work here
lbexit:
if @trancount = 0
commit;
end try
begin catch
declare @error int, @message varchar(4000), @xstate int;
select @error = ERROR_NUMBER(), @message = ERROR_MESSAGE(), @xstate = XACT_STATE();
if @xstate = -1
rollback;
if @xstate = 1 and @trancount = 0
rollback
if @xstate = 1 and @trancount > 0
rollback transaction usp_my_procedure_name;
raiserror ('usp_my_procedure_name: %d: %s', 16, 1, @error, @message) ;
end catch
end
go
I think you are missing an END before the COMMIT call.
See my answer below:
CREATE PROCEDURE main.usp_setup
AS
SET TRANSACTION ISOLATION LEVEL
REPEATABLE READ
BEGIN TRANSACTION
BEGIN TRY
EXEC main.usp_importXml[C:\Users\User\Desktop\people.xml];
END TRY
BEGIN CATCH
INSERT INTO main.errorLog(EntryTime,ErrorNumber,ErrorMessage,ErrorProcedure,ErrorLineNumber,ErrorSeverity,ErrorState)
VALUES (CURRENT_TIMESTAMP,ERROR_NUMBER(),'Failed to import XML',ERROR_PROCEDURE(),ERROR_LINE(),ERROR_SEVERITY(),ERROR_STATE())
declare @message nvarchar(45);
set @message = 'Failed at Import XML - ' + CAST(SCOPE_IDENTITY()AS NVARCHAR(32)) ;
THROW 50001,@message , 20;
END CATCH
BEGIN TRY
EXEC main.usp_afterimport;
END TRY
BEGIN CATCH
INSERT INTO main.errorLog(EntryTime,ErrorNumber,ErrorMessage,ErrorProcedure,ErrorLineNumber,ErrorSeverity,ErrorState)
VALUES (CURRENT_TIMESTAMP,ERROR_NUMBER(),'Failed to Populate',ERROR_PROCEDURE(),ERROR_LINE(),ERROR_SEVERITY(),ERROR_STATE())
set @message = 'Failed to Populate' + CAST(SCOPE_IDENTITY()AS NVARCHAR(32)) ;
THROW 50001,@message , 20;
END CATCH
COMMIT
GO
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.