Как получить выходное значение из хранимой процедуры, если генерируется исключение?

#c# #.net #sql-server #tsql #stored-procedures

#c# #.net #sql-сервер #tsql #хранимые процедуры

Вопрос:

В SQLServer Management Studio, когда я выполняю хранимую процедуру и она выдает исключение, она также возвращает выходные значения.

Я не могу понять, как получить эти значения из C # .NET — при возникновении исключения выполнение останавливается, а выходные значения не заполняются.

Комментарии:

1. Хм, согласно этому сообщению в блоге , выходные параметры не должны заполняться при ошибке, но я только что протестировал, и они, похоже, (для этого случая CREATE PROC FOO @I INT OUTPUT AS SET @I=10 SELECT 1/0 )

2. Зачем вам нужно выходное значение из хранимой процедуры, которая завершилась с ошибкой? Это звучит как плохая практика. Я бы предложил перехватить исключение и использовать в этом случае значения по умолчанию, которые вы предоставляете из своего кода на C #, если они вам действительно нужны, или даже лучше — оставьте всплывающее окно исключения и соответствующим образом обработайте его в приложении.

3. @Ivaylo Slavov, с помощью выходных параметров я могу получить дополнительную информацию, если генерируется исключение

4. В дополнение к моему комментарию выше кажется, что они заполнены, если не возникает ошибка прерывания пакета . SELECT CAST('FISH' AS INT) оставляет их незаселенными.

Ответ №1:

Я почти уверен, что вы можете использовать RAISERROR — это возвращает указанную информацию в приложение. Имейте в виду, что это может быть не идеальной практикой; а также может быть слишком поздно для вас, если у вас нет контроля над хранимой процедурой для реализации этого.

Комментарии:

1. Вы можете получить дополнительную информацию в коллекции ошибок генерируемого исключения SQLException. Кроме того, вы можете использовать RAISERROR, как предложено в ответе выше, и коллекция ошибок будет содержать информацию для каждой ошибки, вызванной RAISERROR

Ответ №2:

Если у вас есть контроль как над хранимой процедурой, так и над кодом, который выполняет хранимую процедуру, то другой альтернативой, которую мы широко используем, является использование выходного параметра хранимой процедуры для возврата кодов ошибок вызывающей стороне (т.Е. @ErrorCode INT = 0 OUTPUT ).

На мой взгляд, это имеет несколько преимуществ по сравнению с возникновением ошибок:

1) Обработка исключений — очень дорогостоящая операция в .net framework. Если все, что вам нужно сделать, это сообщить пользователю, что с введенными данными что-то не так или в базе данных возник конфликт, возврат кода ошибки окажет гораздо меньшее влияние на производительность приложения и сервера, чем выдача и перехват исключений.

2) Если ваша процедура продвинулась достаточно далеко в своей обработке, вы можете заполнить другие параметры. Например, если вам нужно включить информацию о том, у какого пользователя заблокирована запись, вы можете включить эту информацию в другой выходной параметр и создать свое сообщение об ошибке в коде.

3) Может быть проще поддерживать интернационализацию или настройку сообщений с помощью этого метода, чем с помощью сообщений об ошибках, закодированных в хранимых процедурах.

Комментарии:

1. Я уже делаю это. Я устанавливаю @bitErrorCondition1 или @bitErrorCondition2 в зависимости от того, что не так, чтобы мой вызывающий код мог выяснить, что пошло не так, вместо того, чтобы анализировать текст моего RAISERROR вызова. Он отлично работает с .net, но когда я пытаюсь прочитать выходные переменные, заданные sproc из пакета T-SQL, ни один из OUTPUT параметров никогда не устанавливается.

2. Т.е. я хочу по-прежнему использовать RAISERROR , чтобы случайно не продолжить, как будто ничего не пошло не так. Я хочу увидеть ошибку вместо случайного сбоя.

Ответ №3:

Вы можете использовать методы SQLServer для извлечения данных исключения, если вы инкапсулируете свой запрос в блок try catch следующим образом:

 BEGIN TRY
 --SQL Statements
END TRY

BEGIN CATCH
  --exception details

    SELECT ERROR_NUMBER()  
    SELECT ERROR_STATE()  
    SELECT ERROR_SEVERITY()  
    SELECT ERROR_LINE()  
    SELECT ERROR_PROCEDURE()  
    SELECT ERROR_MESSAGE()   

END CATCH
  

Если вы не запускаете блок try catch. SQLServer хранит ошибки в своих журналах, и вы можете прочитать их с помощью t-sql, используя:

 EXEC sys.xp_readerrorlog 1