В Delphi для объекта ошибки не предусмотрен специальный тип, но разработчик может использовать его методы интерфейса Error, предоставляемого многими методами других объектов ADO. Например, тип
TRecordsetEvent = procedure (DataSet: TCustomADODataSet;
const Error: Error;
var Eventstatus: TEventStatus) of object;
используемый для метода-обработчика, вызываемого после обновления набора данных, содержит параметр Error, дающий нам искомую ссылку.
Рассмотрим полезные свойства объекта ошибок ADO.
Свойство
property Description: WideString read Get_Description;
возвращает описание ошибки, переданное из объекта, в котором ошибка произошла.
Свойство
property SQLState: WideString read Get_SQLState; содержит текст команды, вызвавшей ошибку. Свойство
property NativeError: Integer read GetJSIativeError;
возвращает код ошибки, переданный из объекта, в котором ошибка произошла.
Пример приложения ADO
Теперь попробуем применить на практике представленную в этой главе информацию о реализации ADO в Delphi. В качестве примера создадим простое приложение ADO Demo, которое "умеет" отображать пару таблиц БД, сохранять изменения при помощи групповых операций, сортировать записи и устанавливать фильтры на выбранные записи (рис. 19.9).
Рис, 19.9. Главное окно приложения ADO Demo
В качестве источника данных выберем файлы dBase, имеющиеся в демонстрационной базе данных Delphi \Program Files\Common Files\Borland Shared \Data. Для использования в приложении выберем две таблицы: INDUSTRY и MASTER. Они связаны между собой внешним ключом по полям INDCODE и INDUSTRY соответственно.
Таблицу INDUSTRY можно редактировать, она инкапсулирована в компоненте tblindustry типа TADOTable и отображается в левом компоненте TDBGrid. А таблица MASTER инкапсулирована в компоненте tblMaster, предназначена только для просмотра. Эти два компонента связаны отношением ЮДИН-КаМНОГИМ' При ПЪОЩ СВОЖШ MasterSource И MasterFields.
[Листинг 19.2. Секция implementation модуля uMain приложения ADO Demo
implementation
uses IniFiles, FileCtrl;
const slniFileName: String = 'ADODemo.ini';
sEmptyDefDB: String = 'Database path is empty';
sEmptyFilter: String = 'Records for filter is not selected';
{$R *.dfm}
procedure TfmMain.FormShow(Sender: TObject); begin with TIniFile.Create(slniFileName) do
try
DefDBStr : = ReaDString('DefDB', 'DefDBStr', ' ' ) ;
edDefDB.Text := DefDBStr; finally
Free;
end;
SetLength(Bookmarks, 0) ;
end;
procedure TfmMain.FormClose(Sender: TObject; var Action: TCloseAction) ; begin with TIniFile.Create(slniFileName) do
try
WriteString('DefDB', 'DefDBStr', edDefDB.Text); finally
Free;
end;
end;
procedure TfmMain. sbDef DBClick (Sender: TObject) ;
begin
if SelectDirectory(DefDBStr, [], 0) then edDefDB.Text := DefDBStr;
end;
procedure TfmMain. tbConnectClick (Sender: TObject) ;
begin ADOConn.Close;
ADOConn.DefaultDatabase := '';
if tefDBStr = ' ' then begin
MessageDlg(sEmptyDefDB, mtError, [mbOK], 0 ) ;
Abort;
end else begin
ATCom.tefaultDatabase := DefDBStr;
ADOConn.Open;
end;
end;
procedure TfmMain.tbSaveClick(Sender: TObj ect); begin