
- •Bde та ado
- •Введение
- •Введение в базы данных
- •Типы субд
- •Стандарт odbc
- •Технологии взаимодействия delphi с бд
- •Особенности технологии bde
- •Особенности технологии ado
- •Таблицы бд и связи между ними
- •Первичные ключи и индексы
- •Демонстрационная бд "поставщик книг"
- •Использование odbc для подключения источника данных. Внешний псевдоним бд
- •Создание внешнего псевдонима бд
- •Создание проекта с бд в технологии bde
- •Особенности использованияbdeдля соединения с источником данных
- •Структура проекта с бд и визуальными компонентами
- •Активизация проекта
- •Главная форма проекта
- •Модуль данных
- •Создание модуля данныхTDataModule
- •Создание компонента tDatabase
- •Создание компонента tTable
- •Создание компонентаTDataSource
- •Связь модуля главного окна с модулем данных
- •Связь сеткиTdbGrid и навигатораDbNavigatorcисточником данныхTDataSource
- •Связь главный-детальный между наборами данных
- •Задание реляционной связи между наборами данных
- •Активизация наборов данных
- •Недостатки полученных решений и пути их устранения
- •Объекты-столбцы сетки dbGrid
- •Объекты-поля наборов данных
- •Создание объектов-полей
- •Присоединение к наборам данных новых полей
- •Присоединение полей из других таблиц. Подстановочные поля
- •Вычисляемые поля
- •Обработчики событий компонент работы с бд
- •Обработчики событий OnGetText полей нд и компонента визуализации данныхTdbGrid
- •Установка системных переменных в обработчике событяOnCreate
- •Бизнес-правила иобработчики событий компонент работы с бд
- •Implementation
- •Sql запросы к бд
- •КомпонентtQuery
- •СозданиекомпонентаtQuery
- •ИспользованиякомпонентаtQuery
- •Свойство sql
- •Методы Open и ExecSql
- •Параметрические запросы
- •Параметрические запросы и свойство DataSource компонента tQuery
- •Связь главный-детальный с компонентомTQuery в качестве детального набора данных
- •Доступ к полям запроса
- •Обращение к значению поля при помощи свойств объектов-полейValueиAsXxxx
- •Обращение к значению поля при помощи свойств набора данных Fields и FieldValues
- •Обращение к значению поля при помощи функции набора данных FieldByName
- •Программный доступ к данным запроса
- •Общая схема программного доступа к данным запроса
- •Последовательная навигация по записям
- •Обзор событий компонентаtQuery
- •Хранимые процедуры и триггеры
- •Хранимые процедуры
- •Создание хранимых процедур
- •Вызов хранимых процедур
- •Триггеры
- •Наборы данных
- •Обзор событий класса tdbDataSet
- •Реализация каскадных изменений и бизнес-правил
- •Другие события
- •Технология ado
- •Основные особенности технологии ado
- •Реализация технологии ado в Delphi
- •Создание проекта с бд в технологии ado. Установка связи с бд
- •Создание модуля данных
- •Начало настройки связи
- •Выбор провайдера
- •Настройка провайдера
- •Настройка провайдераMicrosoftJet4.0oledbProvider
- •Настройка провайдера Microsoft ole db Provider for odbc Drivers
- •Завершение настройки связи
- •Настройка оставшихся компонент модуля данных
- •Особенности использования компонентов ado
- •Базовые объекты ado
- •ОбъектRecordset
- •ОбъектCommand
- •ОбъектParameter
- •Компонент tadoCommand
- •Свойства, методы и события ado компонентов-наборов
- •Общие свойства с bde-компонентами
- •Специфические свойства
- •Методы класса tCustomAdoDataSet
- •События класса tCustomAdoDataSet
- •Компонент tadoDataSet
- •Компонент tadoTable
- •Компонент tadoQuery
- •Компоненты визуализации данных вDelphi
- •Компонент tdbGrid
- •Свойства
- •Дополнительные возможности сетки
- •Компоненты визуализации полей текущей записи
- •Компонент tdbText
- •Компонент tdbEdit
- •Компонент tdbCheckBox
- •Компонент tdbRadioGroup
- •Списочные компоненты
- •Компонент tdbMemo
- •Компонент tdbRichEdit
- •Компонент tdbCtrlGrid
- •Компонент tdbNavigator
- •Приложение 2. Бд "поставщик книг"
- •Рекомендованная литература
Обработчики событий OnGetText полей нд и компонента визуализации данныхTdbGrid
Событие OnGetText возникает всякий раз, когда программа обращается к полю НД с целью отображения его содержимого в любом визуализирующем компоненте, например TDBGrid. Программист в обработчике этого события должен поместить нужную строку в переменную Text соответсвующего объекта-поля.
Как видно из заголовка нашего примера в нижней сетки DBGrid2 ее 1-ый столбец должен содержать текст, составленный из значений 3-х уже существующих подстановочных объектов-полей tbMoveName, tbMoveAuthor и tbMovePublish набора данных tbMove. Напомним, что по умолчанию Delphi присваивает объекту-полю имя, полученное сцеплением имени НД - tbMove и имени поля - Name.
Чтобы реализовать такое составное поле, воспользуемся обработчиком события OnGetText объекта-поля tbMoveName набора данных tbMove.
В рассматриваемом случае строка Text объекта-поля tbMoveName получается объединением значений в полях tbMoveName, tbMoveAuthor и tbMovePublish.
Перейдите к форме модуля данных и вызовите редактор полей для НД tbMove. Щелкните на поле Name и откройте вкладку Events в окне инспектора объектов. Дважды щелкнув в правой части строки события OnGetText, напишите такой обработчик события:
procedure TDM.tbMoveNameGetText(Sender: TField;
var Text: string;
DisplayText: boolean);
begin
Text := tbMoveName.Value + '/' + tbMoveAuthor.Value + '/' +
tbMovePublish.Value;
end;
Установка системных переменных в обработчике событяOnCreate
Во время работы программы можно заметить, что денежные суммы в сетках DBGrid1 и DBGrid2 содержат округленные до гривен значения. Такое отображение денежных сумм, предлагается по умолчанию, что не всегда допустимо.
С другой стороны программе доступны общесистемные переменные, зависящие от локализации Windows, и в том числе - переменная CurrencyDecimals, с помощью которой можно управлять форматом отображения данных типа currency.
Чтобы в денежных полях отображались не только гривны, но и копейки, создайте такой обработчик события OnCreate главной формы программы:
procedure TFinNakls.FormCreate (Sender: TObject);
begin
//Задается показ типа данных currency с двумя знаками после запятой
CurrencyDecimals := 2
end;
Бизнес-правила иобработчики событий компонент работы с бд
Программа для отображения содержания накладных и связанных с ними списков книг готова. Ее можно запустить и просматривать накладные. Однако не рекомендуется вставлять, редактировать или удалять записи в накладных и списках книг, пока в программе не реализован комплекс бизнес-правил.
Бизнес-правила определяют реакцию системы на добавление, изменение или удаление данных, обеспечивая непротиворечивость и ссылочную целостность БД.
Если, например, для какой-либо накладной удалить запись о книге из ее списка книг, то программа должна автоматически изменить сумму в соответствующей накладной, количество книг на складе и сальдо партнера, в противном случае будут получены недостоверная накладная, неверное количество книг и ошибочное сальдо. Таким образом, корректная реакция программы на удаление записи о книге и есть бизнес-правило удаления книг.
Бизнес-правила разрабатываются на основе тщательного изучения автоматизируемой области человеческой деятельности.
Для файл-серверных систем они обычно реализуются в комплексе обработчиков событий AfterXXXX - BeforeXXXX компонентов-наборов данных TTable или TQuery.
В клиент-серверных и некоторых локальных системах эти действия, как правило, реализуются на сервере БД с помощью триггеров - процедур, которые автоматически запускаются при вставке, изменении или удалении записей.
Рассмотрим небольшой пример, реализующий часть бизнес-правил, связанных с удалением данных о накладной. Перед удалением данных о накладной надо удалить список связанных с ней книг, иначе в таблице MOVEBOOK появятся записи, которые ссылаются на несуществующую запись в таблице NAKLS.
Примечание. Для данного примера при правильном проектировании БД, в частности задания свойства каскадное удаление, собственно корректное удаление будет выполнено автоматически за счет средств самой СУБД. Однако при более сложных бизнес-правилах, когда удаление данных требует дополнительной обработки БД, ответственность за правильное выполнение удаления все равно ляжет на программиста.
Наиболее подходящим местом для реализации этого бизнес-правила является обработчик события BeforeDelete набора данных tbNakls. Это событие автоматически генерируется перед удалением записи.
Перейдите к форме модуля данных, щелкните на НД tbNakls в правой панели модуля и дважды щелкните в строке события BeforeDelete в окне инспектора объектов. Напишите такой обработчик события:
procedure TDM.tbNaklsBeforeDelete(DataSet: TDataSet);
begin
while not tbMove.EOF do // Пока в списке книг есть хотя бы
tbMove.Delete // одна книга, удаляем ее
end;
Следует подчеркнуть, что в обработчике учитывается то обстоятельство, что НД tbMove связан с текущей записью НД tbNakls отношением многие к одному и, следовательно, содержит данные только по тем книгам, которые относятся к удаляемой накладной.
Аналогичным образом с помощью обработчика BeforeDelete набора данных tbMove реализуются бизнес-правила, связанные с удалением информации о книге из списка книг.
Примечание. Следует подчеркнуть, что хранение значений полей таблиц в разных типах БД реализуется по-разному (см. раздел 4). Поэтому для их обработки в Delphi необходимо явно указать, в каком виде представлять эти значения. Например, вражение
tbNaklsNSum.AsFloat
требует представления объекта-поля tbNaklsNSum как числа типа Float, что при вычислениях в Delphi эквивалентно real.
Более точный код обработчика tbNaklsBeforeDelete приведен ниже (проект Chapt04\FieldValues\BiblosPrg.dpr).
type
TDM = class (TDataModule)
DB: TDatabase; //База данных
tbNakls: TTable; //Наборы данных
tbMove: TTable;
tbFirms: TTable;
tbBooks: TTable;
tbTypeNakl: TTable;
DataSource1: TDataSource; //Источники данных
DataSource2: TDataSource;
tbNaklsNaklId: TAutoIncField; //Объекты-поля
tbNaklsNSum: TFloatField;
tbNaklsNPayedSum: TFloatField;
…
tbMoveMoveID: TAutoIncField;
tbMoveMNakl: TIntegerField;
…
tbFirmsFirmID: TAutoIncField;
tbFirmsFName: TStringField;
tbFirmsFFinDelta: TFloatField;
tbFirmsFChgDelta: TFloatField;
…
tbBooksBookID: TAutoIncField;
tbBooksBName: TStringField;
…
tbTypeNaklTypeID: TSmallintField;
tbTypeNaklTName: TStringField;
procedure tbMoveNameGetText(Sender: TField; var Text: string;
DisplayText: boolean);
procedure tbNaklsBeforeDelete(DataSet: TDataSet);
procedure tbMoveBeforeDelete(DataSet: TDataSet);
private
{ Private declarations }
IsNaklDel: boolean; //содержит True, если удаляется накладная
public
{ Public declarations }
end;
var
DM: TDM; //Модуль данных