Вход/Регистрация
Мир InterBase. Архитектура, администрирование и разработка приложений баз данных в InterBase/FireBird/Yaffil
вернуться

Востриков С М

Шрифт:

'C:\IBPRICE.GDB');

Free;

end;

pFIBDatabasel.Open;

CategoriesDataSet.Open;

GoodsDataSet.Open;

end;

He забудем заполнить свойства AutoUpdateOptions, чтобы GoodsDataSet автоматически генерировал значения первичного ключа (рис 2 27)

Можно запустить приложение Двигаясь вверх и вниз по CategoriesGrid, вы можете наблюдать, как автоматически изменяется содержимое в GoodsGrid Связка master-detail уже работает.

FIBPlus позволяет также настраивать некоторые особенности работы механизма master-detail. В частности, как вы уже обратили внимание, в нашем примере мы открывали detail-dataset (GoodsDataSet) "вручную", при помощи явного вызова метода Open В случае с простой связкой это нетрудно, однако если мы используем несколько цепочек master-detail или более длинные цепочки - master-detail-subdetail, то ручное открытие всех запросов может даже привести к ошибке. Вы всегда должны открывать подчиненный запрос после основного.

Чтобы избежать ненужного и совершенно очевидного кодирования, TpFEBDataSet содержит специальное свойство DetailConditions (рис. 2.28).

Рис 2.27. Использование AutoUpdateOptions длл генерации значений первичного ключа GoodsDdtabet

Рис 2.28. Свойаво DetailConditions

Задав ключ dcForceOpen. мы можем быть совершенно уверены, что detail- запрос будет автоматически открыт после открытия master-запроса. Теперь мы можем удалить строку GoodsDataSet.Open из метода CreateForm. Какова бы ни была глубина связок master-detail, все запросы будут открыты в нужном порядке.

Вторая важная опция - это ключ dcWaitEndMastei Scroll Представьте, что пользователь передвигается по CategonesGrid, пытаясь найти нужную категорию товаров. При каждом движении, когда меняется текущая запись в CategoriesGrid, GoodsDataSet автоматически открывает запрос заново. Очевидно, движение по mastei-таблице может вызвать серию довольно "тяжелых" запросов, которые значительно увеличат совершенно бесполезный сетевой трафик. На практике было нужно переоткрыть detail-запрос только один раз, когда пользователь все-таки нашел нужную ему категорию в CategoriesGrid. FIBPlus позволяет избежать ненужных запросов. Если ключ dcWaitEndMasterScroll добавлен в DetailConditions, то detail-запрос переоткрывается только после некоторой паузы (величину паузы можно регулировать, задавая значение свойства WaitEndMasterlnterval).

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

Третий важный ключ в DetailConditions управляет поведением master- таблицы при изменении detail-таблицы. В нашем примере в таблице "Categories" существует поле "GoodsCount", в котором содержится количество наименований товаров для текущей категории. Когда мы добавляем или удаляем наименование товара из категории, то это значение должно меняться. Очевидно, что данный механизм легко реализуется парой триггеров для таблицы "Goods":

CREATE TRIGGER "Goods_AI" FOR "Goods" ACTIVE

AFTER INSERT POSITION 0

AS

BEGIN

update "Categories" set

"GoodsCount" = (select count("Id") from "Goods" where

"IdCategory" = New."IdCategory")

where "Id" = New."IdCategory";

END^

CREATE TRIGGER "Goods_BD" FOR "Goods" ACTIVE

BEFORE DELETE POSITION 0

AS

BEGIN

update "Categories" set

"GoodsCount" = (select count("Id") from "Goods" where

"IdCategory" = Old."IdCategory")

where "Id" = Old."IdCategory";

END^

Давайте рассмотрим последовательность происходящих действий, например при добавлении нового наименования товара для какой-то категории.

В GoodsDataSet формируется значение ключевого поля "Id" при помощи генератора.

Значения полей заполняются пользователем.

После нажатия пользователем клавиши Enter GoodsData подготавливает запрос из свойства InsertSQL к выполнению и заполняет значения параметров соответствующими значениями полей.

Параметр :"IdCategory" заполняется текущим значением поля "Id" из CategoriesDataSet.

Запрос выполняется и выполняется триггер "Goods_AI".

Транзакция GoodsWriteTransaction автоматически подтверждает сделанные изменения при помощи метода Commit.

Выполняется запрос из свойства RefreshSQL, который перечитывает значения полей вставленной в таблицу "Goods" записи, основываясь на известном значении ключевого поля "Id".

В этот момент значение поля "GoodsCount" уже изменилось, но это изменение никак не отражается в CategoriesGrid. Мы должны обновить текущую запись в CategoriesDataSet, чтобы увидеть актуальное значение всех полей. Это можно сделать при помощи явного вызова метода CategoriesDataSet.Refresh. Однако этот же метод нам надо будет вызывать и в случае удаления записи из GoodsDataSet. А если бы нам нужно было создать более сложный механизм взаимодействия между master и detail-таблицами, то, скорее всего, метод Refresh нужно было бы вызывать также и после многих других операций.

  • Читать дальше
  • 1
  • ...
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: