Обработка ошибок SQL Server: исключения и контракт база данных-клиент

мы команда разработчиков баз данных SQL Server. Наши клиенты смешанный мешок C# / ASP.Веб-службы NET, C# и Java, службы Java / Unix и некоторые Excel.

наши клиентские разработчики используют только хранимые процедуры, которые мы предоставляем, и мы ожидаем, что (где разумно, конечно) они рассматривают их как методы веб-службы.

некоторые наши клиентские разработчики не любят исключения SQL. Они понимают их на своих языках, но они не понимают, что SQL ограничен в том, как мы можем общаться.

Я не просто имею в виду ошибки SQL, такие как попытка вставить "bob" в столбец int.

Я также имею в виду исключения, такие как сообщение им, что ссылочное значение неверно, или что данные уже изменились, или они не могут этого сделать, потому что его совокупность не равна нулю.

у них на самом деле нет никаких конкретных альтернатив: они упомянули, что мы должны выводить параметры, но мы предполагаем, что исключение означает " обработка остановлена / свернута спина.

Как люди здесь обрабатывают контракт базы данных-клиента? Либо вообще, либо там, где существует разделение между БД и клиентским кодом.

изменения:

  • мы используем SQL Server 2005 TRY / CATCH исключительно
  • мы регистрируем все ошибки после отката в таблицу исключений уже
  • мы обеспокоены тем, что некоторые из наших клиентов не будут проверять выходные параметры и предполагать, что все в порядке. Нам нужны ошибки, помеченные для поддержка смотреть.
  • все исключение... ожидается, что клиенты выполнят некоторый разбор сообщений для разделения информации и ошибок. Чтобы отделить наши исключения от DB engine и ошибок вызова, они должны использовать номер ошибки (наши все 50,000, конечно)

4 ответов


Ну, я клиентский код обезьяна, которая имеет дело с базами данных много. Вот как я с этим справляюсь.

исключения (raiseerrors), которые происходят в SQL, распространяются обратно вызывающему объекту. Это будет включать ограничения ref, уникальные нарушения индекса, более серьезные проблемы и т. д. В основном все, что не приведет к нормальной работе с данными, должно быть распространено обратно.

вызывающий C# должен иметь это:

catch (SQLException sqlEx)

а затем обработайте исключение как необходимый. Они должны иметь определенный обработчик SQLException. Это важно.

Я обычно держусь подальше от выходных параметров, потому что я считаю, что они связаны с транспортируемыми данными, а не с сообщениями об ошибках, кроме того, я могу проверить исключение для кода ошибки SQL Server, поэтому все необходимые нам данные должны быть в этом исключении.

кроме того, в некоторых случаях с SQL Server у нас есть хранимые процедуры, которые могут вызывать "исключения бизнес-типа". В этих случаях мы добавляем пользовательский номер ошибки (выше 50000) и при необходимости поднимаем эту ошибку в хранимой процедуре. В целом мы стараемся свести их к минимуму, потому что это добавляет сложности, но в некоторых случаях мы находим их необходимыми.

теперь, поскольку клиент ловит SQLException, они могут посмотреть на код ошибки, возвращенный SQL Server в исключении, а затем предпринять какие-либо специальные действия (если необходимо), когда исключение поймано и номер ошибки является определенным значение. Это позволяет вторичный уровень обработки ошибок на основе кода ошибки, если это требуется для пользовательских ошибок (>50000).

Это также позволяет DBAs вызывать пользовательские ошибки и иметь клиентский код последовательный способ борьбы с ними. Затем DBAs должны были сообщить обезьяне клиентского кода, какие пользовательские ошибки были, чтобы они могли подготовиться к ним.

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


Я обычно использую выходной параметр - и определяю возможные значения.

0 = успех
Postive Integer (на вставке скажем) = новый идентификатор строки (@@identity)

Отрицательное Целое Число = Известные Возможные Ошибки
-1 = отсутствует @LastName (или нулевая длина)
-2 = отсутствует @FirstName (или нулевая длина)
...так далее...

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

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

есть и другие методы - это только один, который я использовал с некоторым успехом в прошлом.


вот моя рекомендация:

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

добавьте выходные параметры ErrorMsg и ErrorLog в хранимые процедуры. ErrorMessage будет содержать читаемое человеком сообщение, ErrorLog будет содержать отладочную информацию.
Они будут нулевыми, если return 0
ErrorLog можно использовать для записи любых проблемы, убедитесь, что если вы вставляете их в таблицу, вы делаете это после отката.

используйте TRY-Catch для захвата проблем и создания собственного сообщения и возврата информации, используя вышеуказанные соглашения.


на моей текущей работе мы резервируем исключения для исключительных условиях. Для таких вещей, как плохие параметры или тому подобное, у нас есть стандартные коды возврата - например, недопустимые значения параметров всегда возвращают 98. (почему 98? это потеряно для истории...)

Это не обязательно идеальный b / c и клиент, и SP должны понимать, что означает конкретный код возврата; это плохое разделение проблем.

в особых случаях, мы используем параметры для возвращаемые сообщения и наши пакетные службы используют стандартизированную настройку таблицы # scratch.

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

возможно, вы все должны собраться вместе, чтобы разработать стандартизированные способы обработки клиентского кода. VBA, используемый в Excel, имеет определенные ограничения, которых нет в коде C# и Java, и как похожи Java & C# друг на друга, они не идентичны. если вы собираетесь придерживаться возвращающихся исключений, то если вы можете согласиться на a) известный диапазон сообщений#, которые указывают на "ошибки" исключения и b) стандартизированный макет сообщения, так что стандартизированный разбор может произойти, разработчики будут 90% сделано.