Обработка ошибок SQL Server: исключения и контракт между клиентом и базой данных - PullRequest
6 голосов
/ 17 апреля 2009

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

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

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

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

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

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

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

редактирует:

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

Ответы [ 4 ]

3 голосов
/ 05 августа 2011

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

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

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

catch (SQLException sqlEx)

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

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

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

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

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

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

2 голосов
/ 18 апреля 2009

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

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

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

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

2 голосов
/ 18 апреля 2009

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

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

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

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

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

2 голосов
/ 18 апреля 2009

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

0 = успех
Позитивное целое число (скажем, на вставке) = новый идентификатор строки (@@ identity)

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

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

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

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

...