Визуальные компоненты, реализующие интерфейс пользователя;

· компоненты для связи источников данных с визуальными компонентами, предоставляющими интерфейс пользователя;

· компоненты для визуального проектирования отчетов.

 

Основными механизмами доступа к данным, поддерживаемым в Delphi, являются:

· ODBC - доступ через ODBC-драйверы БД или BDE-драйверы;

· OLE DB - доступ с использованием провайдеров данных (OLE DB - это метод доступа к любым данным через стандартный COM-интерфейс);

· средства dbExpress, использующие легковесные драйверы БД;

· средства доступа к распределенным наборам данных в многозвенной архитектуре.

Самый простой механизм управления данными, использующий ODBC-драйверы, может быть реализован по следующей схеме:

· В модуль данных (или в форму) добавляется компонент набора данных (объект класса TDataSet) и устанавливается связь с источником данных, определяемая свойством DatabaseName. Связь может быть указана одним из трех способов: по имени базы данных, каталогу или псевдониму (способ указания связи может быть ограничен типом источника данных). Список всех псевдонимов доступен на этапе проектирования.

· В модуль данных (или в форму) добавляется компонент источника данных (TDataSourse), являющийся центральным связующим звеном между набором данных и элементами управления, отображающими эти данные. Свойство DataSet компонента типа TDataSourse указывает набор данных, формируемый компонентами таких классов как TTable или TQuery. Если компоненты набора данных и источника данных расположены в модуле данных, то их следует добавить в проект (команда меню File | Use unit).

· В форму добавляются элементы управления для работы с данными, такие как TDBGrid, TDBEdit, TDBCheckbox. Они связываются с компонентом источником данных, который указывается свойством DataSource. Имя поля набора данных определяется свойством DataField.

Графически схему работы с базами данных для двухзвенных архитектур в среде Delphi можно представить следующим образом:

Рис. 76. Cхема работы с базами данных для двухзвенных архитектур в среде Delphi

Наборы данных

Предком всех классов наборов данных является класс TDataSet. Он определяет основу структуры всех наборов данных - массив компонентов типа TField (каждый элемент массива соответствует столбцу таблицы).

Набор данных - это упорядоченная последовательность строк, извлеченных из источника данных. Каждая строка набора данных состоит из полей, указываемых в свойствах класса.

В зависимости от механизма доступа, используемого приложением, базовыми классами набора данных могут быть:

· TTable, TQuery, TStoredProc - для однозвенных или двухзвенных приложений, использующих машину баз данных BDE. Класс TQuery дополнительно позволяет выполнять параметрические запросы;

· TClientDataSet - для реализации клиентского набора данных и для многозвенной архитектуры, использующей распределенный доступ;

· TADODataSet - для приложений, использующих ADO-объекты;

· TSQLDataSet - для доступа к базе данных посредством dbExpress. Этот класс реализует направленный набор данных, функционирующий по принципу курсора. Для такого набора данных не создается кэш памяти на клиенте, и среди методов доступа возможны только методы Next и First. Редактирование записей в направленном наборе данных возможно только явным выполнением SQL-оператора UPDATE или при установке соединения с клиентским набором данных через провайдера;

· TSQLTable и TSQLQuery - для доступа к базе данных посредством dbExpress.

На следующей схеме приведена иерархия классов наборов данных библиотеки VCL:

Рис. 77. Иерархия классов наборов данных библиотеки VCL

Для определения набора данных необходимо задать следующие свойства:

· для класса TTable - значения свойств DatabaseName и TableName;

· для класса TQuery - значение свойства SQL и, возможно, свойства DatabaseName.

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

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

· установить значение свойства Active набора данных равным True во время выполнения приложения (например, Table1.Active:= True;) или в режиме проектирования в инспекторе объектов;

· вызвать метод Open (например, Table1.Open;).

Аналогично, закрыть набор данных можно вызовом метода Close или установив значение свойства Active равным False. Для компонента типа TQuery метод Open может быть выполнен только для закрытого набора данных: попытка открыть уже открытый набор данных инициирует ошибку.

Открытие набора данных влечет за собой:

· инициацию событий BeforeOpen и AfterOpen;

· установку состояния набора данных в dsBrowse;

· открытие курсора для набора данных.

Если в момент открытия набора данных произошла ошибка, то состояние набора данных устанавливается в dsInactive, а курсор закрывается.

При работе с компонентами наборов данных можно обойтись без явного использования компонентов, реализующих соединение с базой данных. Однако некоторые возможности, такие как управление транзакциями или кэшированные обновления, невозможны без компонентов типа TDatabase или TADOConnection. Компонент "база данных" TDatabase применяется для соединения с источником данных через драйверы BDE или внешние ODBC-драйверы. Компонент TADOConnection используется для создания объекта "соединение" при доступе через OLE DB, который инкапсулируется посредством ADO-объектов VCL-библиотеки.

По умолчанию при переходе от одной записи набора данных к другой происходит запись всех сделанных изменений в базу данных. Для того чтобы можно было отменять сделанные изменения или выполнять обновление нескольких записей, применяют кэшированные обновления. Они позволяют значительно снизить сетевой трафик за счет того, что все сделанные изменения хранятся во внутреннем кэше и при переходе от одной записи к другой информация в базу данных не передается. Чтобы включить режим кэшированного обновления, следует установить значение свойства CachedUpdates равным True для компонента набора данных. Для присвоения кэшированного обновления вызывается метод ApplyUpdates, а для отмены - CancelUpdates.

Классы библиотеки VCL

Класс TDATASET

Класс TDataSet является базовым для всех классов наборов данных, наследующих общие свойства и методы этого класса, включая следующие:

· Active - свойство, определяющее, открыт ли набор данных;

· CurrentRecord - свойство, определяющее номер текущей записи набора данных;

· DataSource - свойство, указывающее родительскую таблицу (для таблиц, связанных отношением родительская - дочерняя);

· Bof - свойство, определяющее, находится ли курсор на первой записи набора данных;

· Eof - свойство, определяющее, достигнут ли конец набора данных;

· Bookmark - свойство, указывающее текущую закладку в наборе данных. Закладка отмечает позицию в наборе данных. Используя методы TDataSet.GetBookmark и TDataSet.GotoBookmark, приложение может запоминать и быстро переходить на нужную позицию в наборе данных;

· FieldCount - свойство, указывающее количество полей в наборе данных;

· Fields - свойство, представляющее собой массив полей набора данных и используемое для доступа к этим полям.

Например:

Table1.Edit; // Включение режима редактирования

Table1.Fields.Fields[6].AsString := Edit1.Text;

Table1.Post; // Присвоение изменений

 

Свойство Fields позволяет:

· получить имя поля в текущей структуре записи.

Например:

var S: String;

begin

S := Fields[0].FieldName; // Имя первого поля

S := Fields[1].FieldName; // Имя второго поля

...

end;

· записать в переменную значение поля.

Например:

var s: String; i: Integer; d: TDateTime;

s := Fields[0].AsString;

i := Fields[0].AsInteger;

d := Fields[0].AsDate;

Вместо Fields[n] можно использовать функцию FieldsByName('имя_поля').

Например:

s := Fields[0].AsString;

s := FieldsByName('F1').AsString;

· FieldByName - метод, определяющий поле набора данных по его имени;

Например:

Table1.FieldByName('F1').AsInteger:=StrToInt(Edit1.Text);

· Filter - свойство, в которое заносится строка, определяющая фильтр для набора данных. Фильтр определяет условие, которому должны удовлетворять доступные записи.

Определение фильтра должно удовлетворять следующим правилам:

o фильтр состоит из условий для полей набора данных, объединенных логическими операциями AND и OR. Например: F2 > 10 AND F2 <50;

o если имя поля содержит пробелы, то оно должно быть заключено в квадратные скобки или двойные кавычки. Например: [Field Name1] > 50;

· Filtered - свойство, указывающее, используется ли фильтр, заданный свойством Filter;

· Found - свойство, определяющее, успешно ли выполнен поиск методами FindFirst, FindLast, FindNext или FindPrior;

· Modified - свойство, определяющее, была ли изменена активная запись;

· RecordCount - свойство, содержащее общее число записей в наборе данных;

· State - свойство, указывающее текущее состояние набора данных. Это свойство может принимать следующие значения:

o dsInactive - набор данных закрыт;

o dsBrowse - данные доступны только для просмотра;

o dsEdi - можно изменять активную запись;

o dsInsert - активной записью является новая запись, пока не сохраненная;

o dsSetKey - просмотр ограниченного множества записей (SetRange) или поиск записи;

o dsCalcFields - выполняется обработчик события OnCalcFields;

o dsFilter - выполняется обработчик события OnFilterRecord;

o dsOpening - набор данных находится в процессе открытия.

· Append - метод, добавляющий в конец набора данных новую запись;

· Delete - метод, удаляющий текущую запись из базы данных. Если в момент удаления записи набор данных находится в неактивном состоянии, то инициируется исключение;

· Edit - метод, переводящий текущую запись в режим редактирования;

· Cancel - метод, отменяющий изменения, сделанные в текущей записи;

· Post - метод, выполняющий внесение изменений в базу данных;

· Refresh - метод, выполняющий обновление результирующего набора путем повторного извлечения данных из БД;

· Insert - метод, вставляющий в набор данных новую запись;

· InsertRecord - метод, вставляющий в набор данных новую запись со значениями, которые указаны параметрами метода;

· Close - метод, закрывающий набор данных;

· Open - метод, открывающий набор данных;

· First - метод, устанавливающий курсор на первую запись набора данных и делающий эту запись активной;

· Last - метод, устанавливающий курсор на последнюю запись набора данных и делающий эту запись активной;

· Next - метод, перемещающий курсор на следующую запись набора данных и делающий эту запись активной;

· Prior - метод, перемещающий курсор на предыдущую запись набора данных и делающий эту запись активной.

Класс TDATASOURCE

Класс TDataSource реализует связь между компонентами - наборами данных и элементами управления, используемыми для отображения данных.

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

Класс TDataSource содержит набор свойств и методов, используемых для доступа к набору данных, включая следующие:

· AutoEdit - свойство, определяющее, будет ли автоматически вызываться метод Edit набора данных при получении фокуса элементом управления, ассоциированным с источником данных;

DataSet - свойство, указывающее используемый набор данных.

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

Например:

DataSource.DataSet := Table1;.

· Enabled - свойство, определяющее, будет ли элемент управления отображать ассоциированные с ним данные, или будет отображаться пустым;

· State - свойство, позволяющее определить состояние используемого набора данных.

Например:

if DataSource1.Dataset <> nil then

//Кнопка доступна только в том случае, если набор

//данных находится в состоянии редактирования

//или вставки новой записи

BtnPost1.Enabled := DataSource1.State in [dsEdit, dsInsert];

Класс TTABLE

Компонент типа TTable используется для доступа к базам данных посредством определения источника данных DSN и имени таблицы базы данных. При этом допускается выбор всех полей таблицы или только части полей, а также задание фильтра, определяющего, какие строки таблицы будут доступны.

Компоненты типа TTable могут использовать все свойства и методы, наследуемые от класса TDataSet, а также свойства и методы класса TTable для набора данных, включая следующие:

· DatabaseName - свойство, определяющее имя источника данных DSN;

· CanModify - свойство, определяющее, может ли приложение выполнять вставку, редактирование и удаление записей в таблице;

· DefaultIndex - свойство, определяющее, должны ли данные в таблице быть упорядочены при ее открытии. Если значение свойства равно True (по умолчанию), то выполняется упорядочивание по первичному ключу или уникальному индексу;

· IndexName - свойство, позволяющее определить вторичный индекс, используемый для сортировки открываемого набора данных;

· Exclusive - свойство, позволяющее установить исключительный режим доступа к таблице (значение свойства должно быть определено до открытия таблицы);

· MasterSource - свойство, определяющее имя компонента "источник данных" родительской таблицы для установления отношения между таблицами "родительская-дочерняя";

· MasterFields - свойство, определяющее одно или несколько полей из родительской таблицы, служащих для связи с соответствующими полями данной дочерней таблицы (Это задает отношение между родительской и дочерней таблицами. Поля в списке разделяются точкой с запятой);

· ReadOnly - свойство, позволяющее установить для таблицы режим доступа "только для чтения";

· TableName - свойство, указывающее используемую таблицу базы данных;

· RecNo - свойство, указывающее номер текущей записи набора данных;

· FindKey - метод, выполняющий поиск значения или значений, перечисленных в списке, для ключевого поля;

· FindNearest - метод, перемещающий курсор на запись, содержащую значение, наиболее близкое к указанному значению ключевого поля (поиск может выполняться как по одному значению, так и по нескольким, если используется составной индекс).

Например:

{Изменение значения в компоненте Edit1 автоматически перемещает позицию курсора

в наборе данных Table1}

procedure TForm1.FormActivate(Sender: TObject);

begin

Table1.DatabaseName := 'DBDemos';

Table1.TableName := 'Customer.db';

Table1.Active := True;

Table1.IndexName := 'ByCompany'; {Ключевое поле}

end;

{Обработчик события OnChange (изменение значения) для компонента Edit1}

procedure TForm1.Edit1Change(Sender: TObject);

begin

Table1.FindNearest([Edit1.Text]); {Выполнение поиска}

end;

· Locate - метод, используемый для поиска первого вхождения значения указанного поля или набора полей (если запись найдена, то она становится текущей).

Например:

with Table1 do

Locate('F1;F2',

VarArrayOf(['ABC', 123]),

[loPartialKey]);

Класс TQUERY

Компонент типа TQuery позволяет выполнять любой SQL-оператор, допустимый по синтаксису ODBC-драйвером. Если в качестве выполнимого оператора используется SQL-оператор SELECT, то компонент возвращает набор данных (результирующий набор).

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

Для определения набора данных TQuery следует установить значение свойства SQL и, возможно, свойства DatabaseName (свойство DatabaseName определяет имя источника данных, но для некоторых баз данных можно задать полное имя таблицы, включающее месторасположение файла, в тексте SQL-оператора, - в этом случае свойство DatabaseName не используется). Наиболее правильным подходом все же следует считать тот, при котором имя DSN источника данных указывается свойством DatabaseName, а в SQL-операторе определяется только имя таблицы без определения ее местоположения.

По умолчанию, набор данных, формируемый компонентом типа TQuery, не является редактируемым.

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

· связать компонент TQuery с компонентом типа TUpdateSQL (например: Query1. Query1.UpdateObject:= UpdateSQL1;) и определить для последнего значение свойства ModifySQL (например: update TBL1 set F1 = :F1, F2 = :F2 where F3 = :OLD_F3);

· установить значение свойства RequestLive равным True (поддержка этой возможности зависит от используемой базы данных).

Класс TQuery содержит свойства и методы, используемые для работы с набором данных, включая следующие:

· DataSource - свойство, позволяющее указать родительский набор данных (для отношения "родительский-дочерний").

· Например, если свойство SQL содержит значение 'SELECT * FROM Tbl1 t WHERE (t.FNo = :FNo)', то значение переменной связи :FNo будет определяться из источника данных, указанного свойством DataSource.

· Params - свойство, содержащее список параметров для SQL-оператора.

Например:

Query3.SQL.Clear; // Очищаем значение свойств

// Динамически формируем код SQL-оператора INSERT

Query3.SQL.Add('INSERT INTO ADDRESS (F1, F2)');

// Имена параметров указываются после символа :

Query3.SQL.Add('VALUES (:F1, :F2)');

// Устанавливаем значение параметров

Query3.Params[0].AsString := 'Abc';

Query3.Params[1].AsInteger := 123;

Query3.ExecSQL; // Выполнение SQL-оператора

· RequestLive - свойство, определяющее, будет ли создаваемый набор данных редактируемым (возможность получения модифицируемого результирующего набора зависит от используемого SQL-сервера);

· SQL - свойство, содержащее текст SQL-оператора (для автоматического формирования SQL-оператора можно вызвать из контекстного меню компонента TQuery диалог SQL Builder);

· DatabaseName - свойство, определяющее имя подключаемого источника данных (имя DSN источника данных или имя, введенное классом типа TDatabase);

· ExecSQL - метод, выполняющий SQL-оператор, указанный свойством SQL (для SQL-оператора, создающего набор данных, вместо ExecSQL используется метод Open).

ExecSQL можно вызывать для таких SQL-операторов как INSERT, UPDATE, DELETE, CREATE TABLE и т. п. Если перед вызовом ExecSQL не был вызван метод Prepare, то SQL-оператор будет одновременно и откомпилирован, и выполнен.

· Prepare - метод, выполняющий компиляцию SQL-оператора.

Вызов этого метода перед ExecSQL увеличивает скорость выполнения запроса при многократном повторении вызовов ExecSQL для одного и того же оператора (например, параметризированного запроса). Это позволяет откомпилировать SQL-оператор только один раз, а затем многократно его выполнять.

Класс TSQLTABLE

Класс TSQLTable представляет таблицу базы данных, доступную для клиента как направленный набор данных. Такой набор содержит все записи для полей, определенных в классе TSQLTable. Объект типа TSQLTable должен быть связан с объектом типа TSQLConnection, определяющим соединение с источником данных. Для отображения такого набора данных нельзя использовать таблицу, так как у клиента отсутствует кэш памяти для набора данных. Значение полей таблицы можно отображать компонентами типа TDBText или TDBEdit. Для перемещений по набору записей доступны только методы First и Next.

После размещения в модуле данных или на форме компонента надо выполнить следующие действия:

1. Установить значение свойства SQLConnection компонента TSQLTable, выбрав добавленный ранее компонент типа TSQLConnection из предлагаемого списка.

2. Определить имя таблицы базы данных, используемой для построения набора данных, определив свойство TableName компонента TSQLTable.

Класс TUPDATESQL

Объект типа TUpdateSQL позволяет для наборов данных, созданных с доступом "только для чтения", поддерживать возможность их обновления посредством выполнения SQL-оператора.

Класс TUpdateSQL реализует следующие свойства и методы:

· DeleteSQL - свойство, определяющее SQL-оператор DELETE.

· InsertSQL - свойство, определяющее SQL-оператор INSERT.

· ModifySQL - свойство, определяющее SQL-оператор UPDATE.

· ExecSQL - метод, выполняющий один из заданных SQL-операторов (в зависимости от значения параметра, указываемого следующими константами: ukDelete, ukInsert,ukModify).

Класс TDATABASE

Класс TDatabase реализует работу с объектом "база данных" и предоставляет средства контроля над соединением с базой данных.

Компонент типа TDatabase позволяет управлять транзакциями, использовать настраиваемое подключение к серверу, определять в приложении свои псевдонимы для базы данных.

Для работы с компонентом TDatabase необходимо установить значение свойств AliasName и DatabaseName.

Если значением свойства AliasName указан DSN существующего источника данных, то разработчик может сам определить любой внутренний (для приложения) псевдоним базы данных и задать его в свойстве DatabaseName. В этом случае для любого набора данных в списке значений свойства DatabaseName будет отображаться наряду со всеми доступными DSN источниками данных и внутренний псевдоним, заданный свойством DatabaseName компонента TDatabase.

В том случае, если DSN не определен, то свойство DatabaseName должно содержать полное имя файла базы данных, а свойство DriverName - указывать используемый ODBC-драйвер.

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

· Exclusive - свойство, позволяющее приложению получить исключительный доступ к базе данных (если это поддерживается SQL-сервером);

· InTransaction - свойство, указывающее, был ли выполнен для базы данных вызов метода StartTransaction.

· ReadOnly - метод, указывающий, установлен ли для соединения с базой данных доступ "только чтение".

· TransIsolation - метод, задающий уровень изоляции при управлении транзакциями. Уровень изоляции определяет, как данная транзакция будет взаимодействовать с другими транзакциями, работающими с одними и теми же таблицами. Свойство TransIsolation может быть указано одним из следующих значений:

o tiDirtyRead - транзакция может читать данные, которые были изменены другой транзакцией, но для которых не был выполнен вызов Commit (фиксация изменений);

o tiReadCommitted - позволяет в одной транзакции читать фиксированные изменения, сделанные в базе данных другой транзакцией;

o tiRepeatableRead - истинность данных гарантируется на все время чтения, и транзакция не видит никаких изменений, сделанных другой транзакцией. Прочитанная запись остается постоянной, пока в ней не будут сделаны изменения внутри самой транзакции;

· StartTransaction - метод, открывающий новую транзакцию;

· StartTransaction - метод, открывающий новую транзакцию;

· Commit - метод, выполняющий фиксацию текущей транзакции;

· Rollback - метод, выполняющий откат текущей транзакции;

· Execute - метод, который выполняет указанный параметром SQL-оператор, не возвращающий результирующего набора.

Класс TADOCONNECTION

Класс TADOConnection обеспечивает соединение с данными, доступ к которым реализуется через ADO-объекты.

ADO-объекты позволяют работать с различными хранилищами данных, которые могут и не быть SQL-операторами. Объекты типа TADOConnection используют для доступа к данным OLE DB провайдеры.

Компоненты TADOCommand и TADODataSet связываются с источником данных посредством объекта TADOConnection, указывая ссылку на него как значение свойства Connection.

Для идентификации соединения необходимо определить значение свойства ConnectionString (строка соединения) компонента TADOConnection, которое может основываться на указании:

· datalink-файла;

· строки соединения.

Если в качестве значения свойства ConnectionString указано имя UDL-файла, то настройку соединения можно выполнять автономно от приложения (например, указывая имя базы данных Microsoft SQL Server на текущем ПК).