Проектирование иерархии объектов
Command
Проект, называющийся DataRep, находится в папке этой главы на компакт-диске. В этом параграфе созданы несколько объектов Command, организованных в иерархическую структуру. Названия всех компаний содержатся в таблице Customers. Найдем для каждой компании выписанные ею счета и общее их количество. А для каждого счета - его подробное описание и итоги. Отобразим иерархию записей с помощью элемента управления Grid (элемент управления типа MSHFlexGrid). Элемент управления MSHFlexGrid похож на элемент управления MSFlexGrid, однако предназначен для использования с базами данных и с иерархией элементов управления Command.
Первая колонка содержит имена компаний, вторая — количество счетов для каждой компании, третья - итоговую сумму по всем счетам компании. Последующие колонки должны показывать номер счета, дату заказа и сумму заказа. На рис. 18.2 представлены данные, отображаемые в элементе управления MSHFlexGrid. Обратите внимание, что детали некоторых из заказчиков скрыты. Символ плюса перед именем заказчика означает, что строки с деталями могут быть раскрыты.
Рис. 18.2. Иерархия объектов Command (заказчики-счета-сумма), отображаемые в элементе управления FlexGnd
Выполните следующие действия.
1. Откройте новый Data-проект и создайте объект Connection для базы NWIND, как показано в последнем параграфе.
2. Добавьте новый объект Command (Commandl), откройте диалоговое окно его свойств (щелкните правой кнопкой на имени Commandl и выберите Properties).
3. В окне Properties объекта Commandl установите значение свойства Connection в Connection 1 и выберите Source of Data (Источник данных).
Имена компаний приведены в таблице Customers базы данных NWIND, поэтому выберите строку Table в списке Database Object и Customers - в списке Object Name. После выбора Table в первом раскрывающемся списке появятся имена всех таблиц.
Мы хотим получить счета каждого заказчика. Это означает, что необходимо создать новый объект Command, который будет принадлежать уже созданному объекту Commandl, те будет дочерним для объекта Commandl. Commandl содержит данные о заказчиках, а дочерний объект — счета заказчиков.
4. Щелкните правой кнопкой в окне DataEnvironment на объекте Commandl и выберите из контекстного меню команду Child.
Новый объект Command будет назван Command2. Так как Command2 — это дочерний объект Command1, то для него выполняется точно такое же подключение, как и для объекта Command1. Поэтому окно Connection недоступно. Дочерний объект Command не может иметь собственного подключения. В нашем случае дочерний объект Command возвращает счета из таблицы Orders.
5. Выберите строку Table в списке Database Object и укажите Orders — в списке Object Name.
Так как Command2 — это дочерний объект, то необходимо установить связь (relation) с его с родительским объектом.
6. Переключитесь на вкладку Relation диалогового окна Properties объекта Command2 и выберите Command 1 в качестве родительского объекта в пункте Parent Command (рис. 18.3).
Отношения между объектами определены. Таблицы Customers и Orders используют поле CustomerID в качестве связующего.
7. Выберите значение CustomerID в списках ParentFields и Child Fields/Parameters и щелкните на кнопке Add. В текстовом поле внизу будет показана связь поля CustomerID таблицы Customers с полем CustomerID таблицы Orders.
Добавьте следующий дочерний объект Command, принадлежащий Command2.
Рис. 18.3. Вкладка Relationship: определение отношении между дочерними и родительскими объектами Command
8. Щелкните правой кнопкой на объекте Command2 в окне DataEnvironmentI, выберите команду Child и откройте диалоговое окно Properties для нового объекта Command.
Новый объект Command будет возвращать сумму для каждого счета. Сумма не хранится в таблице базы данных NWIND. Она вычисляется с использованием SQL-оператора. Так как сумма счета часто пересчитывается, то в качестве источника данных следует выбрать View (Просмотр). Это эквивалентно тому, что значение OrderSubtotals будет вычисляться с помощью SQL-оператора всякий раз, когда это требуется. Результатом этого вычисления будет набор записей, как если бы источником данных была таблица. Разумеется, значения, представленные как View, не могут редактироваться.
9. Выберите View в списке Database Object, а в списке Object Name укажите Ок. Subtotals
Диалоговое окно свойств объекта Commands должно выглядеть так, как показано на рис. 18.4.
Следующая задача - добавление отношений между объектом
Commands и его родительским объектом Command2. Для этого выполните следующие действия.
1. На вкладке Relation определите Command2 в качестве родительского объекта и выберите поле OrederID в обоих списках области Relationship Definition (рис. 18.5).
2. Чтобы добавить отношение, щелкните на кнопке Add.
Мы создали иерархию объектов Command: суммы счетов были подключены к группам счетов, которые, в свою очередь, подключены к заказчикам. Зададим способ подведения итогов. Сумма (или итог) обычно задается вначале определения дочернего объекта. Выполните следующие действия.
1. В диалоговом окне Command2 выберите вкладку Aggregates (Итоги).
2. Создайте новый итог и назовите его Order Total (щелкните на кнопке Add и укажите Order Total в приглашении ввода имени нового итога).
3. Для вычисления суммы используется функция SUM, поэтому выберите Sum в списке Function Нам необходимо добавить сумму всех счетов к объекту Commands, который хранит все детали счетов.
4. Выберите объект Commands в списке Aggregate On и имя Subtotal в списке Field.
Рис. 18.4. Источник данных объекта Command3
OrderTotal — это имя итогового значения, вычисляемого для каждого счета. Это значение содержит суммы по всем счетам, выбранным с помощью элемента управления Command2 (рис. 18.6). По отношению к элементу Command2, OrderTotal – одно из полей его набора записей (RecordSet).
Рис. 18.5. Отношение объекта Commands к родительскому объекту
Рис. 18.6. Вкладка Aggregates объекта Command2
Задайте способ подведения итогов для объекта Command 1. Выполните следующие действия.
1. Откройте диалоговое окно свойств Command 1 и выберите вкладку Aggregates.
2. Добавьте новый итог и назовите его TotalOrders. Сумма TotalOrders — количество счетов на каждого заказчика.
3. Выберите Count в списке функций (необходимо посчитать количество счетов, а не их сумму), a Command2 в списке Aggregates и укажите OrderID в списке Field.
Итог TotalOrders вычисляет количество всех счетов в RecordSet объекта Comnnand2 для каждого заказчика. На рис. 18.7 показано задание способа вычисления первого итога объекта Command 1.
Рис. 18.7. Закладка Aggregates объекта Command 1
Вычислите полный итог по всем счетам для каждого заказчика. Выполните следующие действия.
1. Добавьте новый итог с именем CustomerTotal.
2. На этот раз необходимо добавить частичный итог для всех счетов. Для этого выберите функцию SUM, затем в списке Aggregate On - Command2, и в списке Field - OrderTotal.
OrderTotal — это еще один итог, определенный для объекта Command2. По отношению к объекту Objecti, OrderTotal является одним из его полей. После определения всех итогов окно DataEnvironmentI конструктора ActiveX выглядит так, как показано на рисунке 18.8. С помощью вертикальной полосы прокрутки можно увидеть итоги для каждого из объектов — они находятся под соответствующими объектами Command.
Рис. 18.8. Окно DataEnvironment после определения всех итогов
Мы построили объекты Command, которые возвращают нужные записи из базы данных, и определили отношения между ними. Теперь нужно вывести данные на форму. Способы вывода данных на форму описаны в следующих параграфах.