Обработка ошибок
Особенности использования компонента TClientDataSet распространяются также и на обработку ошибок. Ведь клиентский набор данных должен реагировать не только на ошибки, возникшие локально, но и на ошибки сохранения изменений на сервере.
В первом случае разработчик может применить стандартные способы. Это использование блоков try..except или методов обработчиков, унаследованных от класса TDataSet:
- property OnDeleteError: TDataSetErrorEvent; – вызывается при ошибках удаления записей;
- property OnEditError: TDataSetErrorEvent; – вызывается при ошибках редактирования записей;
- property OnPostError: TDataSetErrorEvent; – вызывается при ошибках локального сохранения записей.
Все они используют процедурный тип:
type TDataSetErrorEvent = procedure(DataSet: TDataSet; E: EDatabaseError; var Action: TDataAction) of object;
Здесь, помимо параметров DataSet и Е, определяющих соответственно набор данных и тип ошибки, параметром Action можно задать вариант реакции на ошибку:
type TDataAction = (daFail, daAbort, daRetry);
Где:
- daFail – прервать операцию и показать сообщение об ошибке;
- daAbort – прервать операцию без сообщения об ошибке;
- daRetry – повторить операцию
Например, при возникновении ошибки редактирования набора данных код обработчика может выглядеть следующим образом:
procedure TForml.ClientDataSetEditError(DataSet: TDataSet; E: EDatabaseError; var Action: TDataAction); begin if Not (DataSet.State in [dsEdit, dslnsert]) then begin DataSet.Edit; Action: = daRetry; end else Action: = daAbort; end;
Здесь, если набор данных не находится в состоянии редактирования, это упущение исправляется и операция повторяется.
Итак, с локальными ошибками все обстоит достаточно просто. А как клиентский набор данных "узнает" об ошибке на удаленном сервере? Очевидно, при помощи своего компонента-провайдера. Действительно, компонент TDataSetProvider не только возвращает клиенту несохраненные изменения в пакете Delta (см. выше), но и обеспечивает генерацию события, реакцией на которое является метод-обработчик:
type TReconcileErrorEvent = procedure(DataSet: TCustomClientDataSet; E: EReconcileError; UpdateKind: TUpdateKind; var Action: TReconcileAction) of object; property OnReconcileError: TReconcileErrorEvent;
Обратите внимание, что все параметры похожи на соответствующие параметры локальных обработчиков, но имеют собственные типы. Рассмотрим их.
Параметр UpdateKind содержит указание на тип операции, вызвавшей ошибку на сервере:
type TUpdateKind = (ukModify, uklnsert, ukDelete);
Где:
- ukModify – изменение данных;
- uklnsert – добавление записей;
- ukDelete – удаление записей.