gpt4 book ai didi

.net - SQL Server 存储过程引发多个错误

转载 作者:行者123 更新时间:2023-12-03 01:51:11 25 4
gpt4 key购买 nike

我有一个存储过程,在其中执行 INSERT,然后执行 RAISERROR("MyException", 5, 5),在这种情况下插入失败。

问题是我的 .NET 应用程序的结果是

MyException: Cannot insert the value NULL...

因此它同时返回 2 个异常。

我的 .NET 代码始终只是将整个字符串与“MyException”进行匹配,但这不再起作用。

这是标准吗?如果是这样,这之前怎么可能有效呢?有这方面的设置吗?

编辑:

我使用 .NET 表适配器来处理 SQL 数据库。

版本

Product : Microsoft SQL Server Enterprice(64-bit) Version : 11.0.2100.60 Cluster : False HADR : False

Microsoft Framework .NET 4.6.2

存储过程

ALTER Procedure [dbo].[up_kod_text_save]
-- Add the parameters for the stored procedure here
@entity_id int,
@text varchar(300),
@kod_key int,

@kod_id int,
@korttext varchar(10),
@inaktiv bit,
@primar_extern_kod varchar(300),
@sparad_av varchar(128),
@kod_typ_id int,
@kod varchar(20),
@original_rowver rowversion,
@associerat_varde decimal(18,5),
@beskrivning varchar(2000),
@viktigt_varde bit
AS

BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE @resultat table(kod_id int, uppdat_tidpunkt datetime, rowver binary(8) );

Insert into @resultat
exec up_kod_save @kod_id,@text,@korttext,@inaktiv,@primar_extern_kod,@sparad_av,@kod_typ_id,@kod,@original_rowver, @associerat_varde, @beskrivning,@viktigt_varde

declare @uppdat_tidpunkt datetime
declare @rowver rowversion

declare @tablename varchar(30)
declare @idname varchar(30)

SET @rowver = (SELECT rowver FROM @resultat)
SET @kod_id = (SELECT kod_id from @resultat)

------------------------------------------------------------------------------------
set @uppdat_tidpunkt = getdate()

IF(@kod_key = 2)
BEGIN
ELSE IF(@kod_key = 11)
BEGIN
IF EXISTS ( SELECT akut_checklista_id FROM akut_checklista WHERE akut_checklista_id = @entity_id )
BEGIN
UPDATE akut_checklista
SET [text] = @text,
[kod_id] = @kod_id
WHERE akut_checklista_id = @entity_id
END
ELSE
BEGIN
-- Skapa master-rad
INSERT INTO [akut_checklista] ([text], [kod_id])
VALUES (@text, @kod_id);
set @entity_id = SCOPE_IDENTITY()
END
END
ELSE
BEGIN
RAISERROR ('MyApp_EXCEPTION_UPPDATERAD_AV_ANNAN',16,1)
RETURN
END


SELECT @entity_id as entity_id, @rowver as rowver, @kod_id as kod_id, @uppdat_tidpunkt as uppdat_tidpunkt

up_kod_save只是更新\插入,没有任何事务。然而,如果 rowversion 错误,它可能会失败。

最佳答案

SqlClient API 引发异常时,批处理执行期间发生的严重性为 11 或更高的错误将作为 SqlException 返回到应用程序。各个错误在 SqlException.Errors 集合中返回,SqlException.Message 包含该集合中各个错误的串联文本。

某些 SQL Server 错误将终止批处理,因此在错误发生后不会执行批处理中的后续语句。在这种情况下,仅返回批处理终止错误之前发生的错误。当发生多个错误并且没有一个错误终止批处理时,将返回所有错误。因此,根据具体错误,后续的 RAISERROR 可能不会被执行。

请记住,默认行为是 SQL Server 将继续在内部和外部过程中执行 T-SQL 语句,不会发生批处理终止错误,包括严重性为 16 的 RAISERROR。这可能会导致返回多个错误。

通常,人们不希望在出现错误后继续批处理执行并引发单个错误。可以通过以下一种或多种技术来避免这种情况:

  • 使用结构化错误处理 (TRY/CATCH) 并使用 THROW 而不是 RAISERROR

  • 在每个语句以及控制流语句之后检查@@ERROR

  • 指定 SET XACT_ABORT_ON以便将非批量终止错误提升为批量终止错误并回滚事务

SET XACT_ABORT_ON 是具有显式事务的存储过程的最佳实践,可确保在客户端超时或查询取消时回滚事务。除非 TRY/CATCH block 在范围内,否则批处理也将终止。

就您而言,我建议您向外部过程添加一个 TRY/CATCH block 。 CATCH block 将在内部或外部过程中出现错误后执行。然后,CATCH block 代码可以使用 THROW(SQL Server 2012 及更高版本)引发原始错误,或使用 RAISERROR 严重性为 11 的用户定义错误+ 在客户端应用程序中引发异常。下面是一个例子。

CREATE PROCEDURE [dbo].[up_kod_text_save]
-- parameters here
AS
SET NOCOUNT ON;
BEGIN TRY
-- code here
END TRY
BEGIN CATCH --catch block will be entered after an error in either proc
IF @@TRANCOUNT > 0 ROLLBACK; --needed only if BEGIN TRAN is used
THROW; --this will raise the original error
END;
GO

关于.net - SQL Server 存储过程引发多个错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46643892/

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