Обработка исключений при работе с базами данных


Одним из самых показательных примеров использования экземпляров исключений является известный пример работы с исключениями класса EDBEngineError при работе с базами данных. Особенно это касается баз данных Paradox и dBase, в которых не предусмотрено создание триггеров и ограничений. Последовательность действий следующая:

• Первоначально в секции Uses модуля подключаем блок BDE:
Uses.., BDE;

• В разделе Public объявления класса главной формы приложения объявляем процедуру обработки ошибок, например:

TForm1=Class(TForm)
… // Все иные необходимые объявления
Public
Procedure ShowErrMsg(NErr: Word); End;

• Создаем реализацию этой процедуры в разделе

Implementation модуля:
Procedure TForml.ShowErrMsg(NErr: Word);
Var SErr: String;
Begin
Case NErr Of
DBIERR KEYVIOL: SErr:=’Тайное значение ключа уже имеется!’; DBIERR_REQDERR: SErr:=’Для поля нужно указать значение!’;
Else
SErr:=’Ошибка при работе с данными ‘+IntToStr(NErr); End;
ShowMessage(SErr);
Raise EAbort.Create(»); End;

• В событии OnBeforeAction компонента DBNavigator включаем код:

If Button=nbPost Then // При сохранения данных в таблицах
Try
TableLPost; Except
On E: EDBEngineError Do Form1.ShowErrMsg(E.Errors[0].ErrorCode); End;

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

Procedure TForm1.Table1EditError(DataSet: TDataSet; E: EDatabaseError;Var Action: TDataAction); Begin
ShowMessage(‘Ta6flnna недоступна для изменения данных!’); Action:=daAbort; End;

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

Назначение собственных обработчиков исключений
Вспомним, что когда на каком-либо уровне выполнения программы возникает исключительная ситуация и соответствующим образом не обрабатывается, объект Application выполняет метод HandleException, который проверяет содержимое поля FOnException (фактически проверяет наличие обработчика у события OnException). Таким образом, у программиста есть возможность перекрыть стандартную обработку исключения, определив метод-обработчик для события OnException. Формат этого метода должен соответствовать типу TExceptionEvent. В модуле Forms этот тип объявлен следующим образом:

Procedure(Sender: TObject; E: Exception) Of Object;

Другими словами, тип TExceptionEvent — это процедура, являющаяся объектом. Этот тип имеет поле FOnException, которое и хранит указатель на этот метод.

Известно два основных варианта подключения собственного обработчика события OnException:
— в файле-проекте приложения;
— в файле-главной форме приложения.

В первом случае файлы-формы приложения не загромождаются кодом, обрабатывающим исключения, однако требуется объявление класса, включающего процедуру-обработчик события типа TExceptionEvent. Во втором случае процедура-обработчик события обычно включается в состав класса-формы и делегируется объекту Application в событии OnCreate главной формы. Код в этом случае несколько проще.

а) Для того, чтобы назначить в файле-проекте приложения событию OnException собственный обработчик, надо в общем случае выполнить несколько действий:
• Создать новый проект. Все элементы обработки исключительных ситуаций можно разместить в Dpr-файле. Открыть Dpr-файл можно с помощью команды:
Project \ VeiwSource
• Создать пользовательский класс и его реализацию для создания собственного обработчика события.
• Подключить собственный обработчик события.

Program Project1; UsesSysUtils, Forms,
Unit1 In ‘Unitl.Pas’ {Forml}; Type
TMainExcHandler=CIass // Объявляем собственный класс
Public
Procedure ExcHandler(Sender: TObject; E: Exception); End;
Procedure TMainExcHandler.ExcHandler(Sender: TObject; E: Exception); Begin
<операторы обработки исключительной ситуации>% End;
Var MainExcHandler: TMainExcHandler; {$R *.RES} Begin
MainExcHandler:=TMainExcHandler.Create;// Создаем объект
II Подключаем обработчик
Application.OnException:=MainExcHandler.ExcHandIer; Application.Initialize; AppIication.CreateForm(TForml,Forml); Application.Run;
End.

Параметр Е — это экземпляр класса исключения Exception или одного из его потомков. С его помощью можно получить доступ к полям объекта обработки исключительных ситуаций, объявленных как Public или Published.

В качестве примера <операторов обработки исключительной ситуаций можно использовать выдачу в окне диалога строки-сообщения об ошибке:

MessageDlg(E.Message, mtError, [mbOK], 0);

Пример из подраздела по обработке ошибок в базах данных можно переделать следующим образом.

Procedure TMainExcHandler.ExcHandler(Sender: TObject; E: Exception); Var Serr: String; Begin
If E Is EDBEndineError Then Case E.Error[0].ErrorCode Of
DBIERR_KEYVIOL: Serr:=’TaKoe значение ключа уже имеется!’; DBIERR_REQDERR: Serr:=’Для поля нужно указать значение!’;
… II Другие ошибки, которые можно найти в файле BDE.INT
Else SЕгг:=’Ошибка при работе с данными ‘+IntToStr(NErr); End
Else SErr:=E.Message; ShowMessage(SErr); Raise EAbort.Create(»); End;

б) Для того, чтобы назначить в файле-главной форме приложения событию OnException собственный обработчик, надо в общем случае выполнить несколько действий:
• Объявить собственный обработчик события OnException:

TForml=Class(TForm)
… // Все иные необходимые объявления
Public
// Объявление собственного обработчика исключения
Procedure MyException(Sender: TObjcct; E: Exception); End;

• Создать реализацию объявленной процедуры:

Procedure TForm1.MyException(Sender: TObject; E: Exception);
Begin
If E Is EZeroDivide Then ShowMessage(E.Message)
Else ShowMessage(‘Другая ошибка!’) End;

• Подключить созданный обработчик к объекту Application:

Procedure TForm1.FormCreate(Sender: TObject);
Begin
AppIication.OnException:=MyException; End;

Если необходимость в собственном обработчике исключений отпала, то можно его отключить, переключив вывод сообщений обо всех ошибках на метод ShowException, например, следующим образом:
Application.OnException:=Nil;

Дополнительные функции для работы с исключениями
а) При работе с сокетами Windows могут возникать ошибки и возбуждаться исключения класса ESocketError, которые по умолчанию никак не обрабатываются. Delphi предоставляет пользователям возможность подключить свой обработчик, для чего предусмотрен соответствующий процедурный тип.

Туре
TSocketErrorProc=Procedure(ErrorCode: Integer);

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

SetErrorProc(ErrorProc: TSocketErrorProc): TSocketErrorProc;

Заменяет программу реакции на исключение при возникновении ошибок в сокетах Windows.

б) Для преобразования кодов ошибок Win32 API можно использовать функцию:

SysErrorMessage(ErrorCode: Integer): String;

Возвращает строку сообщения об ошибке, соответствующую кодам ошибок Win32 API.
в ErrorAddr: Pointer;- Возвращает адрес оператора с ошибкой.
г) ExceptProc: Pointer — Переменная, указывающая на необработанные исключения. Можно использовать ее для уточнения данных об ошибке.
д) ErrorProc: Pointer — Переменная, указывающая на RTL обработчик ошибки во время выполнения программы. Оставлена для совместимости с Pascal.
е) В Delphi предусмотрена возможность регистрировать собственные исключения при организации взаимодействия по технологии CORBA, а когда исчезнет необходимость в исключении, то его можно исключить.

Для регистрации следует использовать следующие типы и функцию:
PExceptionDescription=Type Pointer; — Тип указателя, возвращаемый функцией регистрации пользовательского исключения.
PUserExceptionProxy=Type Pointer; — Тип результата пользовательского исключения.
TUserExceptionFactoryProc=Function: PUserExceptionProxy; cdecl; -Процедурный тип, которому должно соответствовать пользовательское исключение.
RegisterUserException(Name, RepositorylD: PChar;
Factory: TUserExceptionFactoryProc): PExceptionDescription;
— Возвращает описание исключения, используя имя (Name) объявленного исключения.

Для каждого, определенного пользователем исключения в IDL файле сервера, необходимо определить потомка от исключения ECorbaUserExcep-tion. Затем для этого исключения следует создать функцию типа TUserExceptionFactoryProc и, наконец, следует зарегистрировать.

Для исключения следует использовать процедуру:
UnRegisterUserException(Description: PExceptionDescription); — Удаляет исключение, используя описание, возвращаемое функцией


Комментарии запрещены.




Статистика