gpt4 book ai didi

c# - 为什么 Entity Framework 为具有事务和 RAISERROR 的存储过程抛出事务计数错误?

转载 作者:行者123 更新时间:2023-11-30 20:30:18 34 4
gpt4 key购买 nike

这是我的带有输出字符串参数的存储过程。

Create
PROCEDURE [dbo].[SpTest]
(@ReturnMessage varchar(50) output)
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRY
BEGIN TRANSACTION;
RAISERROR('asdf',16,1)
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
DECLARE @ErrorMessage VARCHAR(50)= ERROR_MESSAGE();

IF ( @ErrorMessage = 'asdf' )
BEGIN
SET @ReturnMessage = @ErrorMessage;
RETURN;
END;
ELSE


THROW;
END CATCH;
END;

我正在尝试使用 Raiserror 手动捕获错误并将错误作为输出参数发送。当我尝试从 management studio 执行该过程时,该过程工作正常,但是当我从我的应用程序执行时, Entity Framework 向我抛出此错误:

SqlException: Transaction count after EXECUTE indicates a mismatching number of BEGIN and COMMIT statements. Previous count = 1, current count = 0.

但如果我删除 RAISERROR,它会正常工作。

我正在使用 Entity Framework 版本 6 的 C# MVC 应用程序。这是我的 C# 代码:

public ReturnMessageModel Test()
{
ReturnMessageModel result = new ReturnMessageModel();
ObjectParameter returnMessage = new ObjectParameter("ReturnMessage", typeof(String));
using (InsurestEntities db = new InsurestEntities())
{
db.SpTest(returnMessage);
}
result.ReturnMessage = returnMessage.Value.ToString();
}
return result;
}

更新:我在删除此代码时发现错误,交易计数错误已自动解决。

IF ( @ErrorMessage = 'asdf' )
BEGIN
SET @ReturnMessage = @ErrorMessage;
RETURN;
END;

它现在工作正常。我认为 RAISEERROR 在与 EntityFramework

一起使用时必须始终由 THROW 语句处理

最佳答案

确实在 C# 代码中有事务,您只是不知道它们并且没有显式创建它们。 EF 正在为某些操作创建自己的 TransactionScope。

在此存储过程中存在事务的情况下的错误处理将不起作用。您已经发现了原因之一。您还会遇到其他问题,例如在没有事务时尝试回滚。 CATCH block 必须检查 XACT_STATE() block 内的值并相应地采取行动。

如果您想要在存在事务时使用正确的错误处理模式,请参阅 Exception handling and nested transactions :

create procedure [usp_my_procedure_name]
as
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

关于c# - 为什么 Entity Framework 为具有事务和 RAISERROR 的存储过程抛出事务计数错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45030772/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com