Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Proektirovanie_BD_v_Delphi_VTiP.doc
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
5 Мб
Скачать
☆

4.8.1Обработчики событий 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;

4.8.2Установка системных переменных в обработчике событя OnCreate

Во время работы программы можно заметить, что денежные суммы в сетках DBGrid1 и DBGrid2 содержат округленные до гривен значения. Такое отображение денежных сумм, предлагается по умолчанию, что не всегда допустимо.

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

Чтобы в денежных полях отображались не только гривны, но и копейки, создайте такой обработчик события OnCreate главной формы программы:

procedure TFinNakls.FormCreate (Sender: TObject);

begin

//Задается показ типа данных currency с двумя знаками после запятой

CurrencyDecimals := 2

end;

4.9Бизнес-правила и обработчики событий компонент работы с бд

Программа для отображения содержания накладных и связанных с ними списков книг готова. Ее можно запустить и просматривать накладные. Однако не рекомендуется вставлять, редактировать или удалять записи в накладных и списках книг, пока в программе не реализован комплекс бизнес-правил.

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

Если, например, для какой-либо накладной удалить запись о книге из ее списка книг, то программа должна автоматически изменить сумму в соответствующей накладной, количество книг на складе и сальдо партнера, в противном случае будут получены недостоверная накладная, неверное количество книг и ошибочное сальдо. Таким образом, корректная реакция программы на удаление записи о книге и есть бизнес-правило удаления книг.

Бизнес-правила разрабатываются на основе тщательного изучения автоматизируемой области человеческой деятельности.

Для файл-серверных систем они обычно реализуются в комплексе обработчиков событий 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; //Модуль данных

implementation

procedure TDM.tbNaklsBeforeDelete(DataSet: TDataSet);

begin

//Изменяем финансовое или обменное сальдо партнера

//в соответствии с типом накладной:

tbFirms.Edit; //Редактируем НД tbFirms

case tbNaklsNType.AsInteger of

0,3,6: tbFirmsFFinDelta.AsFloat := tbFirmsFFinDelta.AsFloat +

tbNaklsNSum.AsFloat;

4: tbFirmsFChgDelta.AsFloat := tbFirmsFChgDelta.AsFloat +

tbNaklsNSum.AsFloat;

5: tbFirmsFChgDelta.AsFloat := tbFirmsFChgDelta.AsFloat –

tbNaklsNSum.AsFloat;

else tbFirmsFFinDelta.AsFloat := tbFirmsFFinDelta.AsFloat –

tbNaklsNSum.AsFloat;

end;

tbFirms.Post; //Запоминаем сделанные изменения в НД Firms

IsNaklDel := True; //Блокируем часть действий обработчика tbMoveBeforeDelete (описание переменной IsNaklDel см. выше - в секции Private класса TDM)

while not tbMove.EOF do //Пока в списке книг есть хотя бы одна книга,

//удаляем ее

tbMove.Delete; //Удаление текущей записи (книги) в НД tbMove

//Восстанавливаем работу обработчика tbMoveBeforeDelete

IsNaklDel := False;

end;

Полный код обработчика MoveBeforeDelete приведен ниже

procedure TDM.tbMoveBeforeDelete(DataSet: TDataSet);

var

Sum: real;

begin

tbBooks.Edit; //Редактируем НД tbBooks

//Изменяем количество книг на складе с учетом типа накладной:

//если по накладной были получены книги, из общего количества

//книг на складе вычитаем количество книг в удаляемой записи,

//в противном случае - прибавляем

case tbNaklsNType.AsInteger of

0,3,4,6: tbBooksBQuan.Value := tbBooksBQuan.Value - tbMoveMQuan.Value;

else

tbBooksBQuan.Value := tbBooksBQuan.Value + tbMoveMQuan.Value;

end;

tbBooks.Post; //Запоминаем изменения НД tbBooks

//Если обработчик активизирован при удалении накладной, его работу

//нужно завершить, в противном случае (при удалении записи в сетке

// DBGrid2) следует изменить сальдо партнера и сумму в накладной

if IsNaklDel then Exit; //Активизация при удалении накладной?

//-Да. Завершаем работу

Sum := tbMoveMQuan.AsInteger * tbMoveMPrice.AsFloat;

//Изменяем финансовое или обменное сальдо партнера

tbFirms.Edit; //Редактируем НД Firms

case tbNaklsNType.AsInteger of

0,3,6: tbFirmsFFinDelta.AsFloat := tbFirmsFFinDelta.AsFloat + Sum;

4: tbFirmsFChgDelta.AsFloat := tbFirmsFChgDelta.AsFloat + Sum;

5: tbFirmsFChgDelta.AsFloat := tbFirmsFChgDelta.AsFloat - Sum;

else tbFirmsFFinDelta.AsFloat := tbFirmsFFinDelta.AsFloat - Sum;

end;

tbFirms.Post; //Запоминаем изменения в НД Firms

//Изменяем сумму в накладной

tbNakls.Edit; //Редактируем НД tbNakls

tbNaklsNSum.AsFloat := tbNaklsNSum.AsFloat - Sum;

tbNakls.Post; //Запоминаем изменения в НД tbNakls

end;

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]