Вы можете протестировать параметры подключения не выходя из диалога при помощи кнопки Test. Если все указано правильно, то вы увидите сообщение Successful connection.
Управление транзакциями
Необходимо помнить, что любое действие с базой данных происходит в рамках той или иной транзакции. Работа с InterBase основана на явном управлении транзакциями, а поскольку библиотека IBX - это обертка вокруг соответствующих функций InterBase API, то использование этих компонентов также предполагает, что программист явным образом будет управлять транзакциями из своего приложения. Для контроля транзакций в IBX существует специальный компонент TIBTransaction (рис. 2.4):
Рис 2.4. Свойства TIBTransaction
Как видно из рисунка, компонент не слишком перегружен свойствами. Фактически основным является свойство Params, в котором можно указать уровень Изоляции транзакции. Для этого необходимо знать соответствующие системные •константы из InterBase API. Однако для большинства ситуаций вам вполне хватит использования одного из четырех заранее заданных уровней изоляции. Для того чтобы выбрать один из них, можно вызвать редактор компонента (рис. 2.5).
Рис. 2.5. Вызов редактора TIBTransaction
В появившемся диалоге вы сможете указать нужный уровень изоляции, а заодно и увидеть сразу, какими константами он задается (рис. 2.6.).
Рис 2.6. Редактор TIBTransaction
Для большинства случаев рекомендуется использовать режим Read Committed, который позволит запросам в одной транзакции "видеть" изменения, сделанные и подтвержденные в контексте других транзакций.
TIBTransaction ссылается на компонент базы данных при помощи свойства DetaultDatabase. Если также указать свойство DefaultTransaction у TIBDatabase, то в дальнейшем любые компоненты (TIBDataSet, TffiSQL и т. д.), которые ссылаются на TIBDatabase, будут автоматически "подхватывать" и указанную транзакцию.
Теперь рассмотрим свойства AllowAutoStart и AutoStopAction. Как вам уже известно, любой запрос к базе данных должен выполняться в контексте транзакции. То есть, прежде чем выполнить даже простейший запрос вида SELECT * FROM TABLE 1, необходимо предварительно запустить транзакцию при помощи вызова IBTransaction.StartTransaction.
Такой "ручной" вызов не всегда удобен. Более того, каждый раз совершенно определенно известно: если мы хотим выполнить запрос, то мы должны запустить транзакцию. Чтобы избежать лишнего кода, связанного с запуском транзакций, можно установить значение свойства AllowAutoStart равным True. В этом случае если мы попробуем, например, открыть TIBDataSet, то он сам автоматически запустит соответствующую транзакцию.
Аналогичный смысл имеет свойство AutoStop Action. Когда мы закрываем все запросы, выполнявшиеся в контексте автоматически запущенной транзакции, то TIBTransaction выполняет действие, указанное в AutoStopAction. Например, автоматически подтверждает всю транзакцию при помощи метода Commit, если свойство AutoStopAction равно saCommit. Таким образом, разработчику предоставляется возможность указать, как компоненты должны автоматически взаимодействовать друг с другом!
Выполнение запросов при помощи TIBDataSet
В данной главе сознательно не рассматривается работа с TIBTable или TIBQuery, так как авторы книги не считают их использование целесообразным. Если вы все же желаете использовать эти компоненты (например, для облегчения миграции приложения с BDE), то для из>че- ния их функций можно обратиться к документации по аналогичным BDE-компонентам, а также к документации по IBX.
Итак, поместите на форму следующие компоненты:
IBDataSetclass="underline" TIBDataSet;
DataSourceclass="underline" TdataSource
DBGridclass="underline" TDBGrid
Необходимо указать свойства Database и Transaction у IBDataSetl, задать DataSourcel.DataSet равным IBDataSetl, а также указать DBGridl.DataSource равным DataSourcel.
Теперь необходимо указать тот запрос, который мы хотим выполнить, в свойстве SelectSQL у IBDataSetl (рис. 2.7).
Рис 2.7. Редактор свойства SelectSQL
Теперь мы можем открыть запрос прямо в design-time, задав свойство Active в True. Результат наших действий приведен на рис. 2.8.
Рис 2.8. Открытие запроса в IBDataSet1
Чтобы получить то же самое во время выполнения программы, напишите следующий обработчик события OnFormCreate у основной формы приложения'
procedure TForml.FormCreate(Sender: TObject);
begin
IBDatabasel.Open;
IBDataSetl.Open;
end;
He забудьте закрыть подключение к базе данных перед сохранением проекта, иначе попытка IBDatabase I .Open вызовет ошибку. Вы также можете написать этот код иначе: IBDatabasel Connected := True; IBDataSetl.Active := True. Он не вызовет сообщения об ошибке, если IBDatabasel и IBDataSetl были активны в design-time.
Редактируемые запросы
Редактирование данных при помощи визуальных компонентов
Если вы уже запустили пример, представленный выше, и попробовали исправить хотя бы одну запись в таблице, то наверняка получили сообщение, что сделать это невозможно. Причины этого сообщения очевидны, поскольку компонент IBDataSetl имеет только свойство SelectSQL. Это свойство содержит запрос на выборку записей, его выполнение позволяет получить список тех записей из таблицы EMPLOYEE с сервера, которые удовлетворяют условию в WHERE.
А для того чтобы, к примеру, исправить какую-либо запись, необходимо выполнить команду UPDATE. В общем случае выполнение этой команды может вообще не зависеть от нашего запроса в SelectSQL.
Но поскольку TIBDataSet был спроектирован в первую очередь для того, чтобы использоваться совместно со стандартными визуальными компонентами, то он предоставляет нам средства для автоматического выполнения тех модифицирующих запросов, которые необходимы для изменения данных, полученных при помощи SelectSQL. Чтобы окончательно не запутаться, давайте подробнее рассмотрим этот вопрос.
Итак, мы открыли запрос в SelectSQL. Как видно из рисунка, первая полученная запись содержит имя сотрудника Robert. Предположим, мы хотим исправить это имя на John.
В момент изменения произойдет следующее: в локальном буфере IBDataSetl у текущей записи значение поля FIRST_NAME будет изменено с Robert на John. В базе данных данное изменение пока никак не отражается. Чтобы произвести фактическое изменение данных на сервере, необходимо выполнить соответствующий запрос с UPDATE. Этот запрос необходимо заранее указать у компонента IBDataSetl в свойстве ModifySQL:
UPDATE EMPLOYEE
SET
EMP_NO = :EMP_NO,
FIRST_NAME = :FIRST_NAME,
LAST_NAME = :LAST_NAME,
PHONE_EXT = :PHONE_EXT,
HIRE_DATE = :HIRE_DATE,
DEPT__NO = :DEPT_NO,
JOB_CODE = :JOB_CODE,
JOB_GRADE = :JOB_GRADE,
JOB_COUNTRY = :JOB_COUNTRY,
SALARY = :SALARY WHERE
EMP_NO = :OLD_EMP_NO
Как видно из примера, вместо реальных значений в этом запросе указаны параметры, названия которых совпадают с названием реальных полей. Таким образом, когда пользователь изменит значения полей конкретной записи, ю jtBDataSetl сам задаст значения всех параметров, взяв их из соответствующих |полей. В частности, значение параметра :FIRST_NAME будет равно John. Запрос шз ModifySQL выполнится, и только после этого изменения, сделанные пользователем, окажутся в базе данных.