Лабораторная работа №4. Разработка в Delphi программы для работы с СУБД InterBase При создании системы программирования Delphi с самого начала она предназначалась прежде всего для разработки прикладных программ работающих с СУБД различных фирм. Поэтому в Delphi представлены все основные механизмы доступа к данным, известные в мире – ADO, ODBC и др.. Кроме того, Delphi предлагает свои собственные механизмы. К таким относятся BDE и InterBaseExpress. Информация Для создания в Delphi программ, работающих с базами данных InterBase/FireBird, можно рекомендовать использовать механизм доступа к БД InterBaseExpress. Другие варианты имеет смысл использовать, только если подразумевается возможность в дальнейшем перевода БД на другую СУБД. InterBaseExpress включает в себя компоненты, располагающиеся на вкладке InterBase палитры компонентов Delphi. Укажем некоторые из них, которые потребуются нам для создания первой программы. (Мы должны понимать, что с точки зрения Delphi в форме будет располагаться, например, компонент IBDataBase1 типа TIBDataBase . Однако для удобочитаемости мы не будем указывать не имя компонента, не префикс T в типе.) Компонент IBDataBase «умеет» подключаться к базе данных, взаимодействуя с клиентом БД. Компонент IBTransaction служит для управления транзакциями (транзакция – несколько операций с базой данных, которые можно принять, т.е. зафиксировать в базе или отменить). Оба этих компонента связаны друг с другом - у IBDataBase есть свойство DefaultTransaction, которое должно указывать на компонент типа IBTransaction, а у компонента IBTransaction есть свойство DefaultDataBase, которое, наоборот, должно указывать на компонент типа IBDataBase. Компонент IBQuery служит для организации запроса к таблице. Это компонент позволяет делать выборку из таблицы всех записей или только части, всех полей или только части, и притом обеспечивает возможность редактирования данных. Вообще говоря, есть еще компонент IBTable для работы с таблицами, однако опыт показывает, что использование IBQuery - более гибкий вариант. Свойство DataBase у IBQuery должно указывать на компонент типа IBDataBase. Кроме того, свойство UpdateObject должно указывать на компонент IBUpdateSQL. Компонент IBUpdateSQL служит дополнением к IBQuery, если IBQuery используется не только для просмотра данных, но и для добавления, удаления или изменения данных. Кроме этих компонентов, в программе будут использованы компоненты, которые не являются специфичными для InterBaseExpress, а используются для всех механизмов доступа к БД. Компонент DataSource (вкладка DataAccess палитры компонентов) служит для связи между тем, «кто умеет получать данные из базы» и теми, «кто их умеет отображать для пользователя». В роли первого в нашем случае будет выступать компонент IBQuery, поэтому свойство DataSet должно указывать на компонент типа IBQuery. Для отображения данных используются компоненты, располагающиеся на вкладке DataControls палитры компонентов Delphi. У каждого из них есть свойство DataSorce, которое должно указывать на компонент типа DataSorce. Среди них выделим сетку DBGrid для отображения данных в табличной форме, компонент DBEdit для отображения данных в карточной форме, а также DBNavigator, который не отображает данные из таблицы, но представляет собой панель кнопок для организации действий с таблицей (вставка записи, удаление записи, переход в режим редактирования, сохранение или отмена отредактированных данных, переход к следующей/предыдущей записи, в начало/в конец), и одновременно представляет собой индикатор текущего статуса базы данных. При разработке программ, работающих с СУБД InterBase, полезно разделить визуальные компоненты и компоненты доступа к данным. Компоненты доступа к данным в этом случае размещаются в отдельном модуле, который на этапе разработки имеет свою форму, а во время работы программы никогда не отображается в виде окна. Такой модуль называется модулем данных и создается командой File \ New \ DataModule. При разработке достаточно сложной программы окно Form1 из модуля Unit1, которое автоматически появляется при старте программы, удобно сделать главным окном программы, из которого вызываются вторичные окна для просмотра и редактирования таблиц. При работе с данными в Delphi, широко используются так называемые модули данных, которые на этапе разработки отчасти похожи на формы, однако при работе программы они никогда не отображаются как окна, а служат только как контейнеры для невизуальных компонентов, обрабатывающих информацию. Рисунок 1. Структура программы Программа СУБД Модуль uMain (форма fMain) Главное окно программы, отображаемое при старте Модуль uDMMain (модуль данных DMMain) Для соединения с БД через InterBase-клиент Содержит IBDataBase и IBTransaction Модуль uFakultet (форма fFakultet) Отображение данных из таблицы Содержит DBGrid и DBNavigator Красные стрелки- связи между компонентами. Синие стрелки – связи Uses между модулями Модуль uDMFakultet (модуль данных DMFakultet) Содержит запрос IBQuery к таблице Fakultet, IBUpdateSQL для чтения, записи в БД, DataSource для связи IBQuery и визуальных компонентов Примечание. При желании компоненты из всех модулей можно собрать в один модуль, однако тогда программа не будет обладать достаточной гибкостью, что важно для сложных программ. Для нашей же программы мы это сделали еще и в методических целях. 1. Для каждой таблицы удобно сделать отдельный модуль данных, например, DMFakultet в файле uDMFakultet, содержащий компонент qFakultet типа IBQuery для связи с таблицей, компонент dsFakultet типа TDataSource для взаимодействия предыдущего компонента и визуальных компонентов в форме, отображающих данные из таблицы, и компонент uFakultet типа TIBUpdateSQL, хранящий SQL-код для чтения записей, изменения, удаления и добавления. Действия 1. Создание главного окна Создаем новый проект в Delphi и сразу же записываем его (команда File\Save All) в папку с FireBird_Embedding. При этом дадим подходящее название проекту и единственной форме в проекте. Рекомендуем модуль переименовать из Unit1 в uMain, а проект переименовать из Project1 в pGDB. Затем переименуем также форму Form1 в fMain (свойство Name в ObjectInspector). В форме разместим главное меню (компонент MainMenu со страницы Standard палитры компонентов), создадим его структуру(двойной щелчок по этому компоненту вызывает дизайнер меню), но пока не задаем события для пунктов меню. Это соответствует концепции «сначала создадим внешний вид, а затем, наладим функционирование компонентов». 2. Создание главного модуля данных Создадим в проекте модуль данных командой File \ New \ DataModule, сохраним его (команда File\Save As..) в файле uDMMain, а сам модуль данных назовем (свойство Name в ObjectInspector) DMMain. Следует при этом различать модуль как конструкцию Паскаля, означающую часть программы, записываемую в отдельный файл с расширением PAS и модуль данных, как объект, аналогичный форме, но не отображаемый, а служащий контейнером для хранения данных и других объектов. Подчеркиваем, что у нас модуль данных DMMain хранится в модуле (файле) uDMMain (точнее uDMMain.pas). Разместим в модуле данных компонент IBDataBase со страницы InterBase палитры компонентов Delphi. Переименуем его в IB_DB. Разместим в модуле данных компонент IBTransaction со страницы InterBase палитры компонентов Delphi. Переименуем его в IBT. Устанавливаем свойства : 1) У компонента IB_DB в свойстве DefaultTransaction выбираем IBT. 2) У компонента IBT свойство DefaultDataBase должно указывать на компонент IB_DB типа TIBDataBase. 3) Рекомендуем у IBT свойство DefaultAction рекомендуем переключить в значение TACommitRetaining (в этом случае принятые транзакции будут видны и другим пользователям). 4) Вызываем всплывающее меню компонента IB_DB и выбираем команду DataBase Editor. В диалоговом окне устанавливаем параметры. Внимание - параметр Server должен указывать на тот компьютер, где располагается сервер СУБД и Ваша база данных (LocalHost – это особое имя, которое используется, если сервер СУБД и Ваша программа располагаются на одном и том же компьютере). Параметры, установленные в этом диалоговом окне записываются в свойства DataBaseName, LoginPrompt, Params компонента. 5) Для подключения к базе уже на этапе разработки программы устанавливаем свойство Connected в TRUE. При этом придется вводить USERNAME и PASSWORD . Если Connected переключилось в TRUE, значит связь с базой данных установлена, то есть цепочка <Ваша программа> ↔ <IBклиент> ↔ <IBсервер СУБД> ↔ <База Данных> работает во всех звеньях. Во многих ситуациях свойство Connected в режиме разработки программы автоматически переключается в FALSE. Поэтому для надежности напишем программный код автоматического подключения при старте программы. Для этого создадим для модуля данных обработчики событий OnCreate и OnDestroy. (см.рисунок ниже). Для этого выберем сам модуль данных в ObjectInspector, перейдем на страницу Events, сделаем двойной щелчок по строке OnCreate и в созданной системой Delphi заготовке процедуры напишем программный код. Аналогично создается обработчик для события OnDestroy. 3. Создание модуля данных для связи с таблицей Создадим в проекте модуль данных командой File \ New \ DataModule, сохраним его в файле uDMFakultet, а сам модуль назовем DMFakultet. В секцию uses этого модуля добавим uDMmain. Разместим в модуле данных компоненты IBQuery и IBUpdateSQL со страницы InterBase палитры компонентов Delphi и компонент DataSource со страницы DateAccess. Удобно переименовать компоненты, например qFakultet, uFakultet, dsFakultet. Устанавливаем свойства : 1) у компонента qFakultet устанавливаем в свойстве DataBase значение DMMain.IB_DB, а свойство Transaction в DMMain.IBT. 2) у компонента qFakultet в свойстве SQL записываем текст SQL-запроса SELECT SHORTNAME, FULLNAME, DEKAN FROM FAKULTET . Это можно делать также с помощью манипуляций с кнопками <AddTable to SQL> и < AddField to SQL > (см.рисунок ниже) 3) у компонента qFakultet устанавливаем в свойстве UpdateObject значение uFakultet 4) у компонента uFakultet вызываем всплывающее меню и выбираем команду UpdateSQL Editor. В появившемся диалоговом окне устанавливаем первичный ключ, нажав Select Primary Keys. Там же нажмем Generate SQL и просмотрим SQL-команды, которые сгенерированы Delphi. (см.рисунки ниже) 5) Теперь можно протестировать связь с таблицей, установив свойство Active у qFakultet в TRUE. Если это удалось, это означает, что запрос qFakultet работает и выбирает сведения из таблицы. 6) У компонента qFakultet вызываем всплывающее меню и вызываем <редактор полей> Fields Editor. В редакторе полей выбираем команду <Добавить все поля> Add all fields. 7) У компонента dsFakultet типа TDataSource устанавливаем DataSet в qFakultet. 8) У модуля данных в событии OnCreate записываем действия по подключению к базе данных. procedure TDMFakultet.DataModuleCreate(Sender: TObject); begin qFakultet.Open; {или qFakultet.Active := TRUE;} end; В принципе qFakultet уже находится в открытом состоянии, поэтому это делается для подстраховки – дело в том, что при некоторых манипуляциях с запросом в режиме дизайнера он переход в состояние Active =FALSE, и это часто обнаруживается только после запуска программы – а наличие такого программного кода гарантирует, что запрос при старте программы также будет переведен в состояние Active = TRUE;. 9) Для обеспечения фиксации новых записей в базе применим простейший способ – сразу после изменения данных фиксировать транзакцию. Для этого у компонента qFakultet в обработчике события AfterPost (это событие возникает после записи отредактированной записи в таблицу) запишем qFakultet.Transaction.CommitRetaining: procedure TDMFakultet.qFakultetAfterPost(DataSet: TDataSet); begin qFakultet.Transaction.CommitRetaining; end; Аналогичный код записываем в событие AfterDelete (это событие возникает после записи отредактированной записи в таблицу) procedure TDMFakultet.qFakultetAfterDelete(DataSet: TDataSet); begin qFakultet.Transaction.CommitRetaining; end; 4. Создание окна для редактирования таблицы Создадим в проекте еще один модуль с формой командой File \ New \ Form . Удобно сразу же сохранить модуль под именем, например, uFakultet, а форму назвать fFakultet. Действия по разработке окна fFakultet: 1) Запишем в модуль uFakultet в раздел implementation фразу uses uDMFakultet; для связи с указанным модулем. 2) Вставим в форму компоненты DBGrid и DBNavigator со страницы DataControls палитры компонентов. 3) У обоих компонентов в свойстве DataSource укажем DMFakultet.dsFakultet 4) У компонента DBGrid во всплывающем меню выберем Columns Editor... и нажатием на кнопку Add all fields добавим все поля таблицы для отображения в сетке. Поскольку таблица подключена, даже на этапе разработки проекта уже можно видеть данные. 5. Подключение к главному окну После этого в главном модуле uMain в разделе implementation уже можно записать Uses uFakultet; и в обработчик события OnClick для пункта меню записать procedure TfMain.N2Click(Sender: TObject); begin fFakultet.ShowModal; end; Теперь запускаем программу и тестируем ее. Тестирование состоит в проверке возможности добавления записей, редактирования и удаления записей.