#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