Delphi и расширения ADO - Создание приложения для просмотра метаданных
ОГЛАВЛЕНИЕ
Создание приложения для просмотра метаданных
Итак, рассмотрим, как можно применить объекты ADOX в Delphi. В качестве иллюстрации создадим приложение, с помощью которого пользователь сможет:
- просматривать метаданные в виде «дерева» объектов;
- изучать свойства объектов базы данных;
- получать исходный текст хранимых процедур и представлений.
Для выполнения этой задачи создадим новый проект и поместим на главную форму будущего приложения следующие компоненты: TMainMenu, TTreeView, TMemo и TStatusBar. В первую очередь нам следует включить ссылку на библиотеку типов ADOX (она находится в файле MSADOX.DLL), поскольку ADOX не поддерживается в Delphi 5 на уровне компонентов. Для этого следует выбрать Project | Import Type Library главного меню среды разработки Delphi, а затем из списка доступных библиотек типов выбрать Microsoft ADO Ext. 2.1 for DDL and Security. Чтобы избежать конфликтов с именами уже имеющихся классов Delphi (например, TTable), следует переименовать классы ADOX, заменив имена на что-нибудь типа TADOXxxx. Затем нужно убрать отметку из опции Generate Component Wrapper — в данном случае нам нужен только файл *.pas, содержащий интерфейс для доступа к объектам ADOX, а затем нажать кнопку Create Unit. Это приведет к созданию файла ADOX_TLB.PAS, содержащего интерфейс к библиотеке типов ADOX. Создав этот файл, мы должны сослаться на него, а также на модуль ADODB в предложении Uses главного модуля нашего проекта.
Теперь мы готовы к написанию кода для создания объектов ADOX. Создадим пункт меню File | Open Catalog и в обработчике его события OnClick напишем следующий код:
procedure TForm1.OpenCatalog1Click(Sender: TObject);
begin
// Получить имя источника данных (DataSource Name) с помощью стандартной
// диалоговой панели Microsoft
DS := PromptDataSource(Application.Handle, '');
// Если пользователь выбрал источник данных
If DS <> '' Then
begin
// просмотреть метаданные
BrowseData(DS);
end;
end;
Здесь мы использовали метод PromptDataSource, реализованный в модуле ADODB, чтобы вызвать стандартную диалоговую панель Data Link Properties. Если источник данных выбран, то вызывается процедура BrowseData. Назначение этой процедуры — отобразить с помощью компонента TreeView метаданные, извлеченные из базы данных. Текст этой процедуры таков:
procedure TForm1.BrowseData(DataSource: String);
var
RootNode : TTreeNode;
OneNode : TTreeNode;
SubNode : TTreeNode;
I : Integer;
OldCursor : TCursor;
begin
// Заменить стандартный курсор на песочные часы
OldCursor := Screen.Cursor;
Screen.Cursor := crHourglass;
StatusBar1.Panels[0].Text := 'Extracting metadata, please wait...';
// Очистить компонент TreeView
ClearTree;
// и Memo
Memo1.Lines.Clear;
Application.ProcessMessages;
// Соединиться с источником данных
Catalog._Set_ActiveConnection(DataSource);
RootNode := TreeView1.Items.Add(Nil, 'Catalog');
// Добавить таблицы
OneNode := TreeView1.Items.AddChild(RootNode, 'Tables');
For I := 0 to Catalog.Tables.Count-1 do
begin
SubNode := TreeView1.Items.AddChild(OneNode, Catalog.Tables[I].Name);
// Добавить поля, индексы и ключи
ProceedTables(Catalog.Tables[I], SubNode);
end;
// Добавить представления
If CheckViews(Catalog) then
begin
OneNode := TreeView1.Items.AddChild(RootNode, 'Views');
For I := 0 to Catalog.Views.Count-1 do
begin
SubNode := TreeView1.Items.AddChild(OneNode, Catalog.Views[I].Name);
end;
end;
// Добавить процедуры
OneNode := TreeView1.Items.AddChild(RootNode, 'Procedures');
For I := 0 to Catalog.Procedures.Count-1 do
begin
SubNode := TreeView1.Items.AddChild(OneNode, Catalog.Procedures[I].Name);
end;
RootNode.Expand(False);
// Заменить курсор на стандартный и очистить панель состояния
Screen.Cursor := OldCursor;
StatusBar1.Panels[0].Text := '';
end;
Обратите внимание на то, что в приведенной процедуре имеются три цикла для просмотра коллекций Tables, Views и Procedures объекта Catalog. Каждый найденный объект помещен в определенную ветвь компонента TreeView1. Коллекция Tables содержит один или более объектов Table, свойствами которых являются коллекции Columns, Indexes и Keys, и их также следует просмотреть. Это делается с помощью процедуры ProceedTables:
procedure TForm1.ProceedTables(T: Table; N : TTreeNode);
var
I : Integer;
SubNode : TTreeNode;
begin
// Добавить поля
If T.Columns.Count > 0 Then
SubNode := TreeView1.Items.AddChild(N, 'Columns');
For I := 0 to T.Columns.Count-1 do
TreeView1.Items.AddChild(SubNode, T.Columns.Item[I].Name);
// Добавить индексы
If T.Indexes.Count > 0 Then
SubNode := TreeView1.Items.AddChild(N, 'Indexes');
For I := 0 to T.Indexes.Count-1 do
TreeView1.Items.AddChild(SubNode, T.Indexes.Item[I].Name);
// Добавить ключи
If T.Keys.Count > 0 Then
SubNode := TreeView1.Items.AddChild(N, 'Keys');
For I := 0 to T.Keys.Count-1 do
TreeView1.Items.AddChild(SubNode, T.Keys.Item[I].Name);
end;
И снова код содержит три цикла для просмотра коллекций Columns, Indexes и Keys объекта Table .
Вернемся к процедуре BrowseData. Отметим, что перед циклом просмотра коллекции Views следует выполнить проверку того, доступны ли представления для текущего источника данных:
If CheckViews(Catalog) then ...
Это делается, чтобы избежать ошибок и исключительных ситуаций, которые могут возникнуть, если ADOX не поддерживает коллекцию Views для текущего источника данных. Исходный текст функции CheckView показан ниже:
function CheckViews(C : _Catalog) : Boolean;
var
I : Integer;
begin
try
I := C.Views.Count;
CheckViews := True;
except
CheckViews := False;
end;
end;
Теперь компонент TreeView1 заполнен метаданными. Для получения информации о конкретном объекте следует создать для этого компонента обработчик события OnChange. Вот его текст:
procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
begin
If Node.Parent.Parent <> Nil Then
begin
Case Node.Parent.Text[1] of
'C' : ViewColumns(Node.Parent.Parent.Text, Node.Text);
'I' : ViewIndexes(Node.Parent.Parent.Text, Node.Text);
'K' : ViewKeys(Node.Parent.Parent.Text, Node.Text);
'T' : ViewTables(Node.Text);
'V' : ViewProps(Node.Text);
'P' : ProcProps(Node.Text);
end;
end;
end;
Как можно видеть, в этом обработчике события вызываются различные процедуры в зависимости от того, на какой из ветвей компонента TreeView1 пользователь щелкнул мышью. Например, процедура ViewTablesViewColumns, ViewIndexes и ViewKeys используются для изучения свойств полей, индексов и ключей. показывает число объектов внутри выбранной таблицы, а процедуры
Объекты Column, Index и Key обладают немалым количеством свойств, и в рамках данной статьи рассмотреть их подробно невозможно, поэтому в таблице 2 приведены их краткие описания.
Таблица 2
Column | |
---|---|
Attributes | Содержит характеристики поля |
DefinedSize | Содержит максимальный размер поля |
NumericScale | Содержит сведения о положении десятичной точки для числового поля |
ParentCatalog | Указывает на имя каталога, к которому принадлежит поле |
Precision | Содержит максимальную точность данных в поле |
RelatedColumn | Для ключевых полей содержит имя связанного поля |
SortOrder | Указывает порядок сортировки в данных для поля |
Type | Содержит тип данных, хранящихся в поле |
Index | |
Clustered | Указывает, является ли индекс кластерным |
IndexNulls | Указывает, как обрабатываются значения Null |
PrimaryKey | Указывает, реализует ли данный индекс первичный ключ |
Unique | Указывает, должен ли быть уникальным ключ, реализованный в данном индексе |
Key | |
DeleteRule | Указывает, каким образом обрабатывается удаление записи, содержащей первичный ключ |
RelatedTable | Для внешнего ключа указывает имя связанной таблицы |
Type | Содержит тип ключа |
UpdateRule | Указывает, как производится обновление записи, содержащей первичный ключ |
Процедуры ViewProps и ProcProps предназначены для вывода исходного текста представлений и хранимых процедур. Рассмотрим, например, процедуру ProcProps, отображающую свойства хранимой процедуры:
procedure TForm1.ProcProps(Name : String);
var
S : String;
Disp : IDispatch;
Command : _Command;
begin
S := 'PROCEDURE : ' + Catalog.Procedures.Item[Name].Name;
S := S + ^M^J + 'Created : ' +
VarToStr(Catalog.Procedures.Item[Name].DateCreated);
S := S + ^M^J + 'Modified : ' +
VarToStr(Catalog.Procedures.Item[Name].DateModified);
If CmdSupported(Catalog.Procedures.Item[Name]) Then
begin
Disp := Catalog.Procedures.Item[Name].Get_Command;
Command := Disp AS Command;
S := S + ^M^J^M^J + Command.Get_CommandText;
end;
Memo1.Text := S;
end;
В вышеописанном коде мы использовали тот факт, что член коллекции Procedures в действительности указывает на объект ADO Command. Следовательно, мы можем использовать метод Get_Command для получения интерфейса IDispatch объекта Command и использовать их метод Get_CommandText для получения исходного текста хранимой процедуры.
Теперь мы знаем, как использовать объекты ADOX для извлечения и отображения метаданных. Еще одна возможность ADOX, которая будет кратко рассмотрена ниже, — создание баз данных и объектов внутри них без применения сложных DDL-запросов.