#sql-server #asp.net-web-api #stored-procedures
#sql-server #asp.net-web-api #хранимые процедуры
Вопрос:
Я написал некоторый код процедуры, который возвращает значение 1
при успешном запуске.
Но она всегда возвращает -1
(ошибочное значение), когда все проходит успешно ASP.NET Web API
.
Я тестировал в SSMS
этом случае.
USE [MY_DATABASE]
GO
DECLARE @return_value int
EXEC @return_value = [dbo].[API_TO_WEB_CREATE_RESOURCE]
@RES_Size = 3019,
@RES_ContentType = N'image/jpeg',
@RES_OriginalName = N'evolving_google_identity_share.jpg',
@RES_GUID = N'b98bd7ee-cb19-49c8-a8dc-3b92b3210b91',
@RES_Path = N'~/Content/resources\b98bd7ee-cb19-49c8-a8dc-3b92b3210b91',
@RES_Upload_USR_Index = NULL
SELECT 'Return Value' = @return_value
GO
Это возвращает 1
Тот же код в ASP.NET Web API
.
int result = context.API_TO_WEB_CREATE_RESOURCE(
3019,
"image/jpeg",
"evolving_google_identity_share.jpg",
"b98bd7ee-cb19-49c8-a8dc-3b92b3210b91",
"~/Content/resources\b98bd7ee-cb19-49c8-a8dc-3b92b3210b91",
null
);
Это возвращает -1
И это моя процедура.
USE [MY_DATABASE]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:
-- Create date:
-- Description:
-- =============================================
ALTER PROCEDURE [dbo].[API_TO_WEB_CREATE_RESOURCE]
-- Add the parameters for the stored procedure here
@RES_Size int = 0,
@RES_ContentType nvarchar(100) = NULL,
@RES_OriginalName nvarchar(300),
@RES_GUID nvarchar(50),
@RES_Path nvarchar(500),
@RES_Upload_USR_Index int = NULL
AS
BEGIN
DECLARE @RES_RegisteredDatetime datetime = GETDATE()
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
BEGIN TRY
BEGIN TRAN
INSERT INTO
dbo.NS_Resource (RES_Size, RES_ContentType, RES_OriginalName, RES_GUID, RES_Path, RES_Upload_USR_Index)
VALUES (@RES_Size, @RES_ContentType, @RES_OriginalName, @RES_GUID, @RES_Path, @RES_Upload_USR_Index);
PRINT '리소스 추가됨'
COMMIT TRAN
RETURN(1);
END TRY
BEGIN CATCH
ROLLBACK TRAN
DECLARE @ERROR_Msg nvarchar = error_message()
RAISERROR('리소스 추가 중 문제 발생됨 %s', 16, 1, @ERROR_Msg)
RETURN (-1)
END CATCH
END
Краткие сведения
Ожидаемый
Верните значение 1
и вставьте новое значение успешно.
Актуально
- В SSMS
Верните значение 1
и вставьте новое значение успешно.
- В ASP.NET Web API (в этом проблема)
Верните значение -1
и вставьте новое значение успешно.
Комментарии:
1. можете ли вы включить профилировщик и проверить, какие входные значения передаются?
2. @PSK profiler? можете ли вы объяснить подробнее? потому что я нуб.
3. На SQL Server есть инструмент профилирования, который регистрирует все выполняемые запросы, вы можете включить его в своей SSMS.
4. @PSK ок, я отследил свой sql-запрос. В нем говорится
exec [dbo].[API_TO_WEB_CREATE_RESOURCE] @RES_Size=3019,@RES_ContentType=N'image/jpeg',@RES_OriginalName=N'evolving_google_identity_share.jpg',@RES_GUID=N'49af2e21-8683-4972-b888-3e6c588702fa',@RES_Path=N'~/Content/resources49af2e21-8683-4972-b888-3e6c588702fa',@RES_Upload_USR_Index=NULL
из asp.net entity framework.
Ответ №1:
Никогда не рекомендуется иметь несколько return
инструкций в модуле кода, и SQL не является исключением. Попробуйте переписать вашу процедуру следующим образом и посмотрите, поможет ли это:
ALTER PROCEDURE [dbo].[API_TO_WEB_CREATE_RESOURCE]
-- Add the parameters for the stored procedure here
@RES_Size int = 0,
@RES_ContentType nvarchar(100) = NULL,
@RES_OriginalName nvarchar(300),
@RES_GUID nvarchar(50),
@RES_Path nvarchar(500),
@RES_Upload_USR_Index int = NULL
AS
DECLARE @RES_RegisteredDatetime datetime = GETDATE();
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
declare @Ret int = -1; -- Failure by default
BEGIN TRY
BEGIN TRAN
INSERT INTO
dbo.NS_Resource (RES_Size, RES_ContentType, RES_OriginalName, RES_GUID, RES_Path, RES_Upload_USR_Index)
VALUES (@RES_Size, @RES_ContentType, @RES_OriginalName, @RES_GUID, @RES_Path, @RES_Upload_USR_Index);
PRINT '리소스 추가됨';
COMMIT TRAN
set @Ret = 1; -- Success
END TRY
BEGIN CATCH
if @@trancount > 0
ROLLBACK TRAN;
DECLARE @ERROR_Msg nvarchar(2048) = error_message();
RAISERROR('리소스 추가 중 문제 발생됨 %s', 16, 1, @ERROR_Msg);
END CATCH;
return @Ret;
go
Однако для меня все это выглядит немного громоздким. Если вы отправляете ошибку клиенту изнутри catch
блока, этого должно быть достаточно. Это преобразуется в SQLException в C #, поэтому возвращаемое значение становится довольно неактуальным.
Лично я не использую возвращаемое значение; вместо этого я обычно создаю 2 выходных параметра, int
для числа и nvarchar(2048)
для сообщения об ошибке, и присваиваю их значения в catch
блоке без повторного ввода. Когда выполнение завершено, я просто проверяю значение @ErrorNumber
выходного параметра, и если оно не равно ни нулю, ни NULL, я обрабатываю ошибку на стороне клиента.
Комментарии:
1. Отличный совет, и он работает, используя выходное значение вместо возвращаемого value. Ty.