Описание набора данных
Создание набора данных похоже на инструкцию по сборке книжной полки:
Из предыдущего урока вы узнали, что наборы данных состоят из таких элементов как,
- Временные таблицы и их взаимосвязи.
- Источники данных.
Порядок описания и использования наборов данных, следующий:
- Описание временной таблицы для каждой таблицы базы данных, которую хотите использовать в наборе данных.
- Описание набора данных с указанием временных таблиц и их взаимосвязей (если есть).
- Идентификация, описание и подключение источников данных для заполнения набора данных.
- Заполнение набора данных.
- Очистка после использования набора данных.
В этой части вы узнаете, как описать временные таблицы и наборы данных, а в следующих частях урока рассказывается об использовании источников данных, заполнении наборов данных и их очистке.
Временные таблицы
Прежде чем описать набор данных, необходимо определить временные таблицы и поля, которые будут использоваться для его создания.
Временная таблица – это таблица, которая описывается разработчиком и заполняется во время выполнения программы. Временная таблица содержит буферизованные данные в памяти и, при необходимости, обеспечивает прозрачное хранение этих данных на диске. Также как таблицы базы данных, временные таблицы имеют поля и индексы.
Временные таблицы используются для временного хранения и доступа к данным так, как если бы они были сохранены в физической таблице базы данных.
С точки зрения практичности использования описания временных таблиц и наборов данных рекомендуется создавать во встраиваемых файлах (include files, «инклюдники»), один файл на временную таблицу или набор данных. Такие файлы, обычно помещаются в отдельный проект OpenEdge, который может совместно использоваться серверным и клиентским кодом.
Существует два способа создания описаний временных таблиц:
- Вручную. Если временная таблица не является представлением данных в базе данных OpenEdge, то вручную создаётся встраиваемый файл и добавляются операторы для определения временной таблицы.
- Автоматически. Если временная таблица представляет собой копию таблицы в базе данных, то используется специальный мастер New Business Entity Wizard для автоматического создания встраиваемого файла для временной таблицы. Определение временной таблицы не обязательно должно точно соответствовать тому, что находится в базе данных, но большинство полей схожи.
Далее приведён порядок и пошаговые инструкции для создания определений временных таблиц вручную и автоматически.
Создание проекта OpenEdge для разделяемого кода
Как было отмечено, файлы с определением временных таблиц и наборов данных рекомендуется организовывать в одном общем/разделяемом проекте, который будет использоваться как серверным, так и клиентским кодом. Для этого создаётся проект OpenEdge, который имеет подключение к базе данных, что упростит создание встраиваемых файлов для временных таблиц из существующей схемы базы данных OpenEdge.
Действия для создания общего проекта в Developer Studio:
- Выбрать File -> New -> OpenEdge Project.
- В поле Project name указать название проекта, например, Shared.
- Щёлкнуть по кнопке Next.
- В разделе Select AVM and layout options в секции Project layout выбрать Use separate source and r-code directories.
- В поле R-code directory заменить rcode на bin.
- Щёлкнуть Next.
- Поскольку проект не связан с другими проектами, щёлкнуть Next, пропустив раздел настройки PROPATH.
- В разделе Select database connections выбрать базу данных из имеющихся вариантов подключений.
- Щёлкнуть по кнопке Finish.
Создание временной таблицы вручную
При создании временную таблицы вручную вы должны указать каждое поле и индекс в описании временной таблицы. Для каждого поля необходимо указать тип данных, как это делается в операторе DEFINE VARIABLE.
Для описания временной таблицы применяется следующий синтаксис:
DEFINE TEMP-TABLE table-name [NO-UNDO] BEFORE-TABLE before-table-name {FIELD field-name AS data-type} {INDEX index-name [ IS [ UNIQUE ] [ PRIMARY ] ] { index-field }}.
Таблица BEFORE-TABLE используется, когда набор данных обновляется, чтобы исходные и обновлённые данные могли храниться в наборе данных до того, как они будут сохранены в базе данных. На отдельном уроке вы узнаете больше об обновлениях.
В качестве лучшие практики всегда указывайте для временной таблицы параметр NO-UNDO.
Пример описания временной таблицы:
/* ttOrder.i */ DEFINE TEMP-TABLE ttOrder NO-UNDO BEFORE-TABLE bttOrder FIELD OrderNum AS INTEGER FIELD OrderDate AS DATE FIELD ShipDate AS DATE FIELD PromiseDate AS DATE FIELD OrderTotal AS DECIMAL INDEX OrderNum IS UNIQUE PRIMARY OrderNum.
Действия для создания временной таблицы вручную:
- Щёлкнуть правой кнопкой мыши по каталогу src проекта OpenEdge, в котором необходимо создать встраиваемый файл для описания временной таблицы.
- Выбрать в меню New -> ABL Include. Откроется окно мастера New ABL Include.
- Ввести название встраиваемого файла. Как правило название такого файла формируется из префикса tt и имени временной таблицы, описание которой будет храниться в файле. Например, i.
- Щёлкнуть по кнопке Finish. Новый встраиваемый файл будет открыт в OpenEdge Editor.
- Ввести описание временной таблицы в открытом файле. Редактор автоматически выполняет проверку синтаксиса и сообщает об ошибках.
- Сохранить файл.
Создание временной таблицы автоматически
Если временная таблица, которую планируется использовать в наборе данных, частично или полностью соответствует тому, что находится в таблице базы данных, то её описание можно легко создать в Developer Studio. Мастер New Business Entity используется для создания объектно-ориентированных классов бизнес-сущностей (Business Entity), но вы можете использовать его и для автоматического создания встраиваемых файлов временных таблиц для специфической таблицы в базе данных. Созданный этим мастером файл будет необходимо изменить, но его создание будет намного проще, чем вручную вводить описание всех полей временной таблицы в редакторе.
Выполните следующие действия, чтобы создать описание временной таблицы из схемы базы данных:
Шаг |
Действие |
1. | Убедитесь, что проект, в котором будет создан встраиваемый файл, имеет подключение к базе данных. |
2. | Щёлкните правой кнопкой мыши папку, в которой вы хотите создать встраиваемый файл для описания временной таблицы. |
3. | Выберите New -> Business Entity. Откроется мастер New Business Entity. |
4. | Введите имя временной таблицы в поле Business entity name. В качестве наилучшей практики используйте префикс «tt» для имени временной таблицы. |
5. | Щёлкните Next. |
6. | Выберите Select database table. |
7. | Выберите таблицу базы данных, которая будет использоваться для создания описания. Убедитесь, что выбрана база данных и таблица. |
8. | Снимите флажок Expose as a Data Object service. Это важно, иначе мастер создаст много ненужных файлов. |
9. | Щёлкните Finish. |
10. | В редакторе откроется файл класса Business Entity (.cls). Закройте этот файл, так как вы его не будете использовать. |
11. | В Project Explorer удалите файл класса (.cls), щёлкнув по нему правой кнопкой мыши, а затем выбрав Delete. Выберите OK, если вы хотите удалить файл из файловой системы. |
12. | В Project Explorer дважды щёлкните вновь созданный встраиваемый файл для временной таблицы. Он откроется в редакторе OpenEdge. Обратите внимание, что мастер перенесёт любое форматирование отображения, настроенное в базе данных. Вы можете сохранить форматирование в описании временной таблицы. |
13. | В зависимости от полей таблицы базы данных мастер может указывать NO-UNDO в описании временной таблицы, которое он создаёт. Вы всегда должны использовать NO-UNDO для описания временной таблицы. Если NO-UNDO не был сгенерирован, добавьте параметр NO-UNDO в оператор DEFINE TEMP-TABLE (сразу после имени временной таблицы). |
14. | В зависимости от типа таблицы, используемой для генерации кода, в описании временной таблицы могут быть поля типа VOID. Удалите все поля типа VOID в описании. Они представляют собой данные, которые нельзя использовать для заполнения набора данных. |
15. | Удалите последний оператор в файле, DEFINE DATASET. |
16. | Вы можете внести другие изменения во временную таблицу, включая добавление вычисляемых полей, которые требуются приложению. Вы также можете удалить любые поля, которые не требуются приложению. |
17. | Сохраните файл и закройте его. |
Примечание. Существует ещё один инструмент, который можно использовать для создания кода для описания временных таблиц и наборов данных. Доступ к нему осуществляется с помощью перспективы Tools for Business Logic для Developer Studio. В этой перспективе (с подключением к базе данных) вы можете создать компонент бизнес-логики, который предоставляет вам графическое представление наборов данных и временных таблиц, которые могут использоваться для генерации встраиваемых файлов.
Наборы данных
После того, как временные таблицы подготовлены, с помощью оператора DEFINE DATASET описывается набора данных, который будет состоять из этих таблиц. Подобно описанию временных таблиц в отдельных встраиваемых файлах, описание набора данных также хранится в отдельном встраиваемом файле.
Оператор DEFINE DATASET – это сложный оператор со множеством компонентов. Вы будете использовать его для:
- именования набора данных и указания временных таблиц, составляющих этот набор;
- описания отношений данных между временными таблицами.
Описание набора данных
Упрощённая версия синтаксиса оператора DEFINE DATASET:
DEFINE DATASET <dataset-name> FOR <temp-table-name> [,<temp-table-name> ]…
Здесь,
- <dataset-name> – стандартное имя ABL-объекта;
- <temp-table-name> – имя временной таблицы.
Пример кода, описывающего набор данных:
/* dsOrder.i */ {include/ttOrder.i} DEFINE DATASET dsOrder FOR ttOrder.
В этом примере описание временной таблицы ttOrder представлено встраиваемым файлом ttOrder.i и набор данных состоит из единственной таблицы. Использование одиночных таблиц позволяет описывать двухмерные наборы данных, например, строки и столбцы данных. Однако приложения баз данных обычно полагаются на наборы из связанных данных для выполнения общих операций с базой данных, включая отношения между родительскими и дочерними элементами, например, клиентами и их заказами, или заказами и связанными с ними элементами заказов.
Наборы данных позволяют легко описать подобные взаимосвязи между данными как часть набора данных путём добавления отношений данных к оператору DEFINE DATASET.
Описание отношений данных
Второй шаг в создании набора данных заключается в описании взаимосвязей между таблицами, составляющими набор данных. Это делается добавлением одной или более спецификации отношения данных в оператор DEFINE DATASE.
Язык ABL использует информацию об отношениях данных для извлечения дочерних записей, связанных с родительской записью, и для поддержания реляционной целостности данных между указанными таблицами.
Отношение данных является частью описания набора данных и определяет взаимосвязь между родительской и дочерней временными таблицами в наборе данных. Связь описывается путём указания полей таблиц, которые образуют первичное отношение внешних ключей между ними.
Упрощённый синтаксис для описания отношения данных:
DATA-RELATION <data-relation-name> FOR <parent-temp-table-name>, <child-temp-table-name> RELATION-FIELDS (parent-field1, child-field1 [, parent-fieldn, child-fieldn ]…)
Здесь,
- <data-relation-name> – имя объекта отношения данных;
- <parent-temp-table-name> и <child-temp-table-name> – имена родительской и дочерней таблиц;
- RELATION-FIELDS – определяет связь между полями временных таблиц.
Примечание: для создание наиболее эффективных отношений данных поля RELATION-FIELDS должны быть проиндексированы.
Пример описания отношений между данными
Приведённые далее программный код демонстрирует описание многотабличного набора данных с временными таблицами ttOrder и ttOrderline. Код выполняет следующее:
- описывает набор данных из двух временных таблиц;
- описывает связь между этими двумя таблицами;
- указывает, что связь между двумя таблицами основана на значениях поля ordernum.
/* dsOrderOrderLine.i */ {include/ttOrder.i} {include/ttOrderLine.i} DEFINE DATASET dsOrderOrderLine FOR ttOrder, ttOrderline DATA-RELATION drOrderOrderLine FOR ttOrder, ttOrderline RELATION-FIELDS (ordernum,ordernum).
Примечание. Хотя в этом примере поля двух таблиц имеют одинаковое имя, вы также можете указать для связи поля, которые имеют разные имена.
В наборе данных можно указать больше одного отношения данных. Например, представим, что набор данных состоит из трёх таблиц, где таблица ttOrder связана с таблицей ttOrderLine, которая в свою очередь связана с таблицей ttItem. В таком варианте потребуется описать два отношения данных, где:
- отношение между ttOrder и ttOrderLine определяется по индексированному полю OrderNum;
- отношение между ttOrderLine и ttItem по индексированному полю ItemNum.
/* dsOrderOrderLineItem.i */ {include/ttOrder.i} {include/ttOrderLine.i} {include/ttItem.i} DEFINE DATASET dsOrderOrderLineItem FOR ttOrder, ttOrderLine, ttItem DATA-RELATION drOrderOrderLine FOR ttOrder, ttOrderLine RELATION-FIELDS (Ordernum, Ordernum) DATA-RELATION drOrderLineItem FOR ttOrderline, ttItem RELATION-FIELDS (Itemnum, Itemnum).