Реферат.

Наряду с реляционным подходом к разработке информационных приложений для баз данных все большее распространение получает объектный подход. Это связано с ограниченностью самой реляционной модели, например, при описании и манипулировании сложными структурами данных, усложнением запросов при выборках данных из нескольких таблиц, снижением роизводительности при соединениях больших таблиц и др.

Объектный подход дает такие преимущества как:

- естественное представление данных;

- возможность разработки структур любого уровня сложности;

- высокую производительность процесса разработки;

- использование объектно-ориентированных CASE-средств проектирования и разработки приложений.

В последнее время появляется все больше объектных и объектно-ориентированных СУБД таких как Versant, Jasmine, ODB-Jupiter, Cache и др., которые приобретают все большую популярность и признание. Некоторые эксперты полагают, что, несмотря на доминирование на рынке реляционных СУБД, за объектными СУБД будущее.

Высокоэффективная постреляционная система управления базами данных Cache разработана в русле новых технологий, объединяющих сервер многомерных данных и многофункциональный сервер приложений. Главные свойства Cache – развитая объектная технология, быстрота разработки Web-приложений, усовершенствованная база SQL и уникальная технология получения данных – позволяют достичь такого высокого уровня производительности и масштабируемости, который был недоступен в рамках реляционной технологии.

НЕ нашли? Не то? Что вы ищете?

Оглавление

Цель разработки. 4

Отчет о проделанной работе. 4

Создание классов. 4

Класс «Компания». 5

Создание класса "Компания" с помощью мастера. 5

Определение свойств класса "Компания". 8

Создание метода класса с помощью мастера. 13

Компиляция класса. 15

Листинг (класс "Компания"): 16

Класс «Адрес». 17

Создание класса "Адрес". 17

Листинг (класс "Адрес"): 21

Класс «Сотрудник». 22

Создание класса "Сотрудник". 22

Листинг (класс "Сотрудник"): 26

Класс Руководитель. 27

Создание класса "Руководитель". 27

Листинг (класс "Руководитель"): 28

Создание объектов. 28

Исходные данные. 29

Справка. 29

Запуск Cache` Studio. 30

Создание программы в среде Cache` Studio. 31

Пункт 1. 32

Пункт 2. 33

Пункт 3. 33

Пункт 4. 34

Пункт 5. 35

Листинг программы.. 35

Запуск программы в в среде Cache` Terminal 36

Работа с Порталом.. 38

Работа с объектной базой данных. 42

Программа для обращения к объектному представлению.. 42

Просмотр списка всех сотрудников и руководителей. 43

Просмотр списка всех руководителей. 44

Просмотр информации о сотруднике (руководителе), ID которого указан как входной параметр 45

Листинг программы просмотра списка сотрудников Prog3. 46

Проверка работоспособности программы.. 47

Работа с глобалами. 49

Исходные данные. 50

Листинг класса Компания. 50

Листинг класса Адрес. 50

Листинг класса Сотрудник. 51

Листинг класса руководитель. 51

Структура и содержание таблиц базы данных. 51

Содержание таблиц базы данных. 52

Сохранение объектов в глобалах. 53

Просмотр глобалов в среде Cache` Портал. 53

Глобал данных для классов "Компания" и "Адрес". 54

Глобал данных для классов "Сотрудник" и "Руководитель". 55

Программа для работы с глобалами. 55

Составить список компаний. 56

Удалить сотрудника (руководителя). 57

Назначение руководителя. 57

Листинг программы работы с глобалами. 59

Экспорт/ Импорт глобалов. 61

Список используемой литературы. 62

Цель разработки

1.  Разработать систему классов, которая дает обзор:

·  основных типов классов

·  основных типов данных (для атрибутов классов)

·  основных связей между объектами

2.  Разработать пример создания классов с помощью мастера

3.  Разработать пример работы с Cache` Портал, Cache` Terminal, Cache` Studio

4.  Разработать пример работы с БД Cashe при помощи прямого доступа к глобалам, объектного подхода и реляционного представления, SQL-запросов

Отчет о проделанной работе.

В ходе работы были на примере объектной СУБД Cache` были изучены методы работы с данными, которые используют объектный подход, реляционное представление и низкоуровневый доступ к внутренним структурам. Так же были рассмотрены элементы Cashe куба, необходимые для разработки БД(Cache` Studio), ее администрирования(Cache` Портал) и отладки различных функций и процедур(Cache` Terminal). Итогом разработки являются разработанная система классов, программы, написанные в среде Cache` Studio и примеры, демонстрирующие работу с Cache` Портал.

Создание классов

Определим в среде Cache` Studio четыре класса:

Класс "Компания" - хранимый класс. Содержит свойства:

    название - строковое (обязательное, уникальное), адрес - встроенный объект класса "Адрес", сферы деятельности - массив или список строковых значений. Метод класса - Создать - создает и сохраняет в базе данных новый объект класса "Компания" (и встроенный в него объект класса "Адрес").
    Входные параметры: название компании, город, улица, номера.
    Выходной параметр: ссылка на созданный объект.

Класс "Адрес" - встроенный. Содержит свойства:

    город - строковое, улица - строковое, номера - строковое в формате дом-корпус-квартира. Метод экземпляра - "Полный адрес" - возвращает строку, содержащую название города и улицы в предопределенном формате
    (например, "г. Москва, 2-я Бауманская, 5").

Класс "Сотрудник" - хранимый. Содержит свойства:

    имя - строковое (обязательное), компания - ссылка на объект класса "Компания" (обязательное), должность - строковое, Метод экземпляра - "Информация о сотруднике" - возвращает строку, содержащую имя сотрудника, название компании, где он работает, и его должность.

Класс "Руководитель" - производный от класса "Сотрудник". Содержит свойства:

    дата назначения - дата и время (обязательное), Переопределенный метод экземпляра - "Информация о сотруднике" - возвращает строку, содержащую имя, название компании и сведения, с какого времени он является руководителем компании.

Для создания классов используется среда Cache` Studio.

Для определения методов и запросов классов используются соответствующие мастера.

Для просмотра созданных классов используется среда Cache` Портал (раздел Classes, пакет USER) .

Класс «Компания»

Создание класса "Компания" с помощью мастера

Чтобы создать класс необходимо запустить Studio. Для этого щелкаем на куб Cache (на панели задач) и из меню выбираем "Студия". Здесь можно создавать классы, их свойства, методы:

http://*****/metpbd/lab/class/class_html_m2c7dc4e4.png

Создание нового класса поддерживается мастером. Щелкните правой кнопкой мыши по значку "Классы" в окне "Рабочая поверхность", выберите в контекстном меню "Создание Класс":

http://*****/metpbd/lab/class/class_html_4397df8b.png

На экране появится "Мастер создания класса". Определение нового класса начинается с задания его имени и описания. Создадим класс "Компания", который является хранимым классом:

http://*****/metpbd/lab/class/class_html_2620a138.png

Имя класса - Organization, сопровождается его кратким описанием (пакет User используется по умолчанию, его можно не менять). Если затем Вы щелкните по "Далее", то попадете на следующий экран, где устанавливается тип класса. На данной форме, в соответствии с нашим условием, мы устанавливаем тип класса Persistent (Хранимый):

http://*****/metpbd/lab/class/class_html_m.png

Результат, полученный при создании класса, можно просмотреть в окне, демонстрирующим иерархию классов:

http://*****/metpbd/lab/class/class_html_25532aac.png

Определение свойств класса "Компания"

Для того, чтобы определить свойства класса необходимо в меню выбрать пункты Классhttp://*****/metpbd/lab/class/class_html_14c6894b.gifДобавитьhttp://*****/metpbd/lab/class/class_html_14c6894b.gifНовое свойство:

http://*****/metpbd/lab/class/class_html_33acafb2.png

Или на панели инструментов выбрать значок http://*****/metpbd/lab/class/class_html_6de0be25.png. Откроется окно определения нового свойства:

http://*****/metpbd/lab/class/class_html_m5d6c8f41.png

Задаем свойство компании - Название (Name). Далее выбираем тип свойства. Т. к. название компании имеет строковый тип, то из списка, который появляется после нажатия на кнопку "Просмотр", выбираем String:

http://*****/metpbd/lab/class/class_html_6af6322b.png

Нажимаем кнопку ОК:

http://*****/metpbd/lab/class/class_html_39e76d63.png

По условию работы данное свойство является обязательным и уникальным:

http://*****/metpbd/lab/class/class_html_3824afa2.png

Далее нажимаем кнопку "Готово". Свойство создано.

Создаем свойство компании "адрес":

http://*****/metpbd/lab/class/class_html_m54c2b48c.png

Свойство компании "адрес" является встроенным объектом класса "Адрес":

http://*****/metpbd/lab/class/class_html_73879a36.png

Нажимаем кнопку ОК:

http://*****/metpbd/lab/class/class_html_7ea56c9b.png

Далее определяем свойство "Сферы деятельности":

http://*****/metpbd/lab/class/class_html_71d584c1.png

Свойство "Сферы деятельности" представляет собой массив или список строковых значений:

http://*****/metpbd/lab/class/class_html_292200fc.png

Создание метода класса с помощью мастера

Чтобы определить новый метод, необходимо нажать кнопку http://*****/metpbd/lab/class/class_html_m6ba55a3b.pngна панели инструментов либо выбрать следующие пункты меню: Классhttp://*****/metpbd/lab/class/class_html_14c6894b.gifДобавитьhttp://*****/metpbd/lab/class/class_html_14c6894b.gifНовый метод. Откроется мастер создания метода. Определяем название нового метода:

http://*****/metpbd/lab/class/class_html_728233a9.png

Далее определяем список аргументов и их тип:

http://*****/metpbd/lab/class/class_html_m46e01c05.png

Выбираем выходное значение. Нажимаем на кнопку "Просмотр" и выбираем из открывающего списка тип возврата:

http://*****/metpbd/lab/class/class_html_m29098d7c.png

Список аргументов и выходное значение:

http://*****/metpbd/lab/class/class_html_164ff4bd.png

Далее в теле метода создаем новый экземпляр класса Organization и определяем входные аргументы, сохраняем экземпляр. В итоге, получаем:

ClassMethod CreateOrganization(OrganizationName As %String, City As %String, Street As %String, Number As %String) As Organization{
set NewOrganization = ##Class(User. Organization).%New()
set NewOrganization. OrganizationAddress = ##Class(User. Address).%New()
set NewOrganization. Name = OrganizationName
set NewOrganization. OrganizationAddress. City = City
set NewOrganization. OrganizationAddress. Street = Street
set NewOrganization. OrganizationAddress. HomeNumber = Number
do NewOrganization.%Save()
Quit NewOrganization
}

Компиляция класса

После создания класса, его свойств и методов класс необходимо откомпилировать. Использование классов возможно только после их компиляции. При этом может быть задано, подлежит ли компиляции один - единственный, все измененные или же вообще все классы. Если компилируется только один класс, компилятор сначала проверяет, модифицировался ли родительский класс этого класса с момента его последней компиляции (или, возможно, он еще ни разу не компилировался). Таким образом, автоматически компилируются все измененные классы, от которых был произведен компилируемый класс. Чтобы откомпилировать класс, необходимо нажать кнопку http://*****/metpbd/lab/class/class_html_m4f72dbaa.pngна панели инструментов.

Листинг (класс "Компания"):

// ------  класс является хранимым,  т. е. наследует возможности от системного класса %Library. Persistent

Class User. Organization Extends %Persistent   
{

//------ свойство класса "Название" является строкой. Оно обязательно и уникально;
Property Name As %String [ Required ]; 
Index NameIndex On Name [ Unique ];

//------- свойство Адрес как встроенный объект класса Address;
Property OrganizationAddress As Address; 

//------ свойство Сферы деятельности как список строковых значений;
Property Business As list Of %String;

//-----метод класса.
//------ Аргументы метода :  OrganizationName - строковый тип, City - строковый тип, Street -
строковый тип,  Number - строковый тип.  
//----- Метод возвращает ссылку на экземпляр объекта;

ClassMethod CreateOrganization(OrganizationName As %String, City As %String, Street As %String, Number As %String) As Organization 
{
//-----Создаем новый экземпляр класса Organization в памяти процесса.
//------ Локальная переменная NewOrganization содержит объектную ссылку на новый экземпляр (на созданный объект).

set NewOrganization = ##Class(User. Organization).%New() 

//-----аналогично создаем встроенный объект класса "Адрес".
set NewOrganization. OrganizationAddress = ##Class(User. Address).%New()

//-----устанавливаем свойства объектов на основе входных аргументов.

set NewOrganization. Name = OrganizationName
set NewOrganization. OrganizationAddress. City = City
set NewOrganization. OrganizationAddress. Street = Street
set NewOrganization. OrganizationAddress. HomeNumber = Number

//-------Сохраняем новый экземпляр в базе данных.

do NewOrganization.%Save()

//----- Завершаем процедуру и возвращаем ссылку на созданный объект

Quit NewOrganization
}

}

Класс «Адрес»

Создание класса "Адрес"

Класс является встроенным и содержит следующие свойства:

·  город - строковое;

·  улица - строковое;

·  номера - в формате дом-корпус-квартира;

Метод экземпляра – «Полный адрес» - возвращает строку, содержащую название города и улицы в предопределенном формате (например, «г. Москва, 2-я Бауманская, 5»).

С помощью мастера создадим класс "Адрес":

http://*****/metpbd/lab/class/class_html_366c3f84.png

Класс является встроенным:

http://*****/metpbd/lab/class/class_html_3f325c3d.png

Далее нажимаем кнопку "Готово".

Определение свойств класса "Адрес".Определим свойство "Город":

http://*****/metpbd/lab/class/class_html_m239dfc3c.png

Данное свойство является строкой:

http://*****/metpbd/lab/class/class_html_fabc88.png

Нажимаем кнопку "Готово".

Аналогичным образом определяется свойство "Улица".

Теперь определим свойство "Номера", тип которого является строка в формате дом-корпус-квартира:

http://*****/metpbd/lab/class/class_html_m2aea5065.png

Укажем тип свойства как строковое:

http://*****/metpbd/lab/class/class_html_m1494a3f2.png

Далее прописываем шаблон:

http://*****/metpbd/lab/class/class_html_mc8d596e.png

Нажимаем кнопку "Готово".

Метод класса "Адрес". Вызываем мастер создания метода.

http://*****/metpbd/lab/class/class_html_2f951717.png

Выбираем тип возвращаемого значения.

http://*****/metpbd/lab/class/class_html_5a2b0612.png

Метод не имеет аргументов, поэтому нажимаем кнопку "Готово". Далее прописываем тело метода. Компилируем класс.

Листинг (класс "Адрес"):

// имя класса - Address. % SerialObject-системный супер-класс. От него образуются встраиваемые классы

Class User. Address Extends %SerialObject [ ClassType = serial ]
{
// свойство City имеет строковый тип
Property City As %String;

// свойство Street имеет строковый тип
Property Street As %String;

// Это свойство, содержащее значение. Это свойство типов данных. Данный класс типов данных поддерживает параметр PATTERN. PATTERN — задает шаблон, которому должна соответствовать строка ".N1""-"".N1""-"".N"
Property HomeNumber As %String(PATTERN = ".N1""-"".N1""-"".N");

//метод экземпляра. Возвращает строку в формате город - улица-дом
Method FullAddress() As %String
{
//this - ссылка на экземпляр объекта. This используется только в методе экземпляра. В методе класса она отсутствует
  Quit "г." _ ##this. City _ ", ул." _ ##this. Street _ ", " _ ##this. HomeNumber 
}
}

Класс «Сотрудник»

Создание класса "Сотрудник"

Данный класс является хранимым и содержит следующие свойства:

·  имя – строковое (обязательное);

·  компания — ссылка на объект класса «Компания» (обязательное);

·  должность – строковое.

Метод экземпляра – «Информация о сотруднике» - возвращает строку, содержащую имя сотрудника, название компании, где он работает и его должность. Создадим новый класс:

http://*****/metpbd/lab/class/class_html_m3cbb4a29.png

Тип данного класса - хранимый:

http://*****/metpbd/lab/class/class_html_546794b.png

Определение свойств класса "Сотрудник". Определим свойство "Имя":

http://*****/metpbd/lab/class/class_html_m3bee5dd0.png

Оно является строковым и обязательным:

http://*****/metpbd/lab/class/class_html_m681231f4.png

Укажем тип свойства:

http://*****/metpbd/lab/class/class_html_5b7880ce.png

Нажимаем кнопку "Готово".

Далее определим свойство "Компания". Оно является ссылкой на объект класса «Компания». Данное свойство обязательно:

http://*****/metpbd/lab/class/class_html_m78de92dd.png

Свойство класса "Должность" определяется аналогично свойству "Имя". Оно также является строковым, но не является обязательным.

Метод класса "Сотрудник". Запускаем мастер создания метода. Определяем название метода, тип его выходных параметров:

http://*****/metpbd/lab/class/class_html_m1452e0.png

Укажем тип выходного значения как строковое:

http://*****/metpbd/lab/class/class_html_5a2b0612.png

Далее прописываем тело метода и компилируем класс.

Листинг (класс "Сотрудник"):

// класс является хранимым, т. е. наследует возможности от системного класса % Library. Persistent

Class User. Worker Extends %Persistent 
{

//свойство WorkerName имеет строковый тип и является обязательным
Property WorkerName As %String [ Required ];

// свойство WorkerOrganization является ссылкой на объект класса "Компания". Свойство обязательное
Property WorkerOrganization As Organization [ Required ];

// свойство WorkerPost имеет строковый тип
Property WorkerPost As %String; 

// Метод экземпляра. Возвращает строку, содержащую имя сотрудника, название компании, где он работает, и его должность.
Method WorkerInfo() As %String
{
// this - ссылка на экземпляр объекта.

Quit "Имя работника: " _ ##this. WorkerName _", компания: " _ ##this. WorkerOrganization. Name _ ", должность: " _ ##this. WorkerPost
}

}

Класс Руководитель

Создание класса "Руководитель"

Класс "Руководитель" является производным от класса «Сотрудник». Содержит свойства:

o  дата назначения – дата и время (обязательное),

Переопределенный метод экземпляра – «Информация о сотруднике» - возвращает строку, содержащую имя, название компании и сведения, с какого времени он является руководителем компании.

Вызываем мастер создания класса:

http://*****/metpbd/lab/class/class_html_m45a21ddd.png

Далее выбираем базовый класс - класс Worker:

http://*****/metpbd/lab/class/class_html_m372adcd.png

Далее определяем свойства и методы класса аналогично предыдущим пунктам.

Затем определяем тело метода и компилируем класс.

Листинг (класс "Руководитель"):

// класс Manager является производным от класса «Сотрудник». Manager - хранимый класс

Class User. Manager Extends User. Worker [ ClassType = persistent ]
{
//свойство HireDate имеет тип %TimeStamp отметка - времени, состоящая из даты и времени TIMESTAMP
Property HireDate As %TimeStamp [ Required ];

// Переопределенный метод экземпляра – «Информация о сотруднике» - возвращает строку, содержащую имя, название компании и сведения, с какого времени он является руководителем компании
Method WorkerInfo() As %String
{
Quit ##this. WorkerName _" - " _ ##this. WorkerOrganization. Name _ ", руководитель с " _ ##this. HireDate
}

}

Создание объектов

Приведем пример программы на языке Cache` Object Script в среде Cache` Studio и вызов ее из среды Cache` Terminal. Программа выполняет следующие действия:

    Пункт 1. Отображать запрос на ввод и ввести с консоли имя сотрудника, название компании и должность. Пункт 2. Создать новый объект класса "Руководитель", если должность "руководитель" или объект класса "Сотрудник" в противном случае. Определить поля объекта: имя и должность. Пункт 3. Используя запрос SQL, получить ссылку на компанию с указанным названием и присвоить эту ссылку полю компания. Пункт 4. Если компании с указанным названием не существует, то ввести с консоли по запросу город, улицу и номера, создать новый объект класса компания, вызвав соответствующий метод класса. Присвоить ссылку на компанию объекту сотрудника из п.2. Пункт 5. Сохранить новый объект "Сотрудник" (или "Руководитель") в базе данных.

Ввод выполняется в цикле. Признак завершения цикла - ввод специального символа (например, пустой строки).

Исходные данные

Созданные классы:

    Класс "Адрес" (листинг) Класс "Компания" (листинг) Класс "Сотрудник" (листинг) Класс "Руководитель" (листинг)

Справка

При выполнения были изучены основы языка Cache` Object Script и использованы следующие команды и операторы:

    для ввода данных команду read, для вывода - write, для присвоения значения переменной - set, для вызова процедуры - do, для организации циклов - for или while, для задания условия блок - if { } else { }, для выходя из процедуры - quit, для конкатенации - оператор "_".

Для создания процедур можно использовать встроенные методы:

    %New() - создать объект, %Save() - сохранить объект в базе, %OpenId() - открыть объект, хранящийся в базе, по его идентификатору, %DeleteId() - удалить объект из базы данных, SetAt() - сохранить значение элемента массива, GetAt() - извлечь значение элемента массива.

Для обращения к базе данных можно использовать класс %ResultSet и его методы:

    Prepare() - подготовить запрос, Execute() - выполнить запрос, Next() - извлечь строку из результата запроса, Data() - получить значение поля в текущей строке.

Для работы с глобалами можно использовать функции:

    $Get - получить значение глобала, $Order - получить очередной в последовательности глобал, $Data - проверить существование глобала.

Запуск Cache` Studio

Cache` Studio - это интегрированная, визуальная среда создания объектно-ориентированных баз данных и Web-приложений. Она имеет следующие особенности для обеспечения быстрой разработки:

    Возможность редактирования определений классов, CSP-страниц, программ на Cach` Object Script(COS) в единой интегрированной среде; Полнотекстовое редактирование с подсветкой команд, а также проверкой синтаксиса на следующих языках: Cach` Object Script, Basic, Java, SQL, JavaScript, HTML, и XML; Поддержка команды разработчиков, работающих с общим репозиторием кода приложения; Наличие отладчика; Организация кода в проект; Наличие мастеров, позволяющих создавать классы, методы, свойства, связи, WEB-формы.

Исходный код приложения Cache` оформляется в виде проекта. Проект может содержать следующие компоненты: классы, программы, CSP-файлы. Можно создавать новые проекты, открывать и изменять существующие. Также существует возможность добавления или удаления компонентов из проекта.

Для запуска "Студии" необходимо на панели задач нажать правой кнопкой мыши на значок Cache` :

http://*****/metpbd/lab/create/create_html_1fdff318.png

и в выпадающем меню выбрать "Студия":

http://*****/metpbd/lab/create/create_html_589a93bb.png

После запуска Студии появится окно, содержащее несколько закладок. Внешний вид среды разработки Cach` Studio:

http://*****/metpbd/lab/create/create_html_m65fc6689.png

Создание программы в среде Cache` Studio

Создаем в среде Cache` Studio файл программы, который имеет расширение MAC. Для этого необходимо справа на "рабочей поверхности" правым щелчком мыши на пункте "Программы" вызвать меню и выбрать в нем пункт "Создание Программа":

http://*****/metpbd/lab/create/create_html_307441b6.png

Результат можно увидеть ниже:

http://*****/metpbd/lab/create/create_html_m6d056f7d.png

Сохраняем программу с именем, которое необходимо: "Файл" > "Сохранить как…"

Теперь мы можем на языке Cache` Object Script писать программу. Рассмотрим подробно действия, которые должна выполнять программа.

Пункт 1

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

Код программы выглядит так:

write !,"Завершение ввода происходит по двойному нажанию на 'Enter' ",!
for
{
read !,"Введите имя сотрудника: ",Name
quit:Name=""
read !,"Введите название компании: ",CompanyName
quit:CompanyName=""
read !,"Введите должность: ",Post
quit:Post=""
}

Команда write выведет сообщение на экран монитора. Восклицательный знак выполняет переход на новую строку. Далее организован цикл с помощью безаргументной формы команды for, в которой нет ни переменной цикла, ни начального, ни конечного значения. Команда read выдаст подсказку пользователю о том, что необходимо ввести, и введет ответы пользователя в переменные Name, CompanyName, Post. Далее идет постусловная конструкция вида: quit:<условие>. Команда quit выполнится, если истинно условие.

Пункт 2

Пример: Создим новый объект класса "Руководитель", если должность "руководитель" или объект класса "Сотрудник" в противном случае. Определить поля объекта: имя и должность.

Основной синтаксис для создания новых экземпляров объектов - это использование метода класса %New:

set oref = ##Class(ClassName).%New()

, где oref - ссылка OREF на новый объект, ClassName - это имя класса, чувствительно к регистру букв и может содержать имя пакета, ##Class() - это макровызов, который используется для вызова методов класса.

В нашем случае необходимо создать объект класса "Руководитель", если должность "руководитель". Для этого используется конструкция if:

if (Post="руководитель"){code} else {code}

В блоке кода создается новый объект:

set NewWM = ##Class(User. Manager).%New()

Далее идет строка, необходимая для указания даты и время назначения сотрудника, если он является руководителем. Используется системная переменная $Horolog, которая содержит текущее время в виде пары чисел: первое число задает внутренний формат даты, второе число задает количество секунд, прошедших с полуночи. Второй аргумент функции $ZDateTime - это формат возвращаемой даты.

Создание объекта класса "Сотрудник" в блоке кода else:

set NewWM = ##Class(User. Worker).%New()

Полностью эта часть кода выглядит так:

if (Post="руководитель")
{
set NewWM = ##Class(User. Manager).%New()
set NewWM. HireDate = $ZDateTime($Horolog,3)
}
else 
{
set NewWM = ##Class(User. Worker).%New()
}
set NewWM. WorkerName = Name //определение поля имя
set NewWM. WorkerPost = Post //определение поля должность

Пункт 3

Пример: Используя запрос SQL, получим ссылку на компанию с указанным названием и присвоим эту ссылку полю компания.

Используем объект класса %ResultSet для подготовки динамического SQL-запроса:

set rset = ##class(%ResultSet).%New("%DynamicQuery:SQL")
Do rset. Prepare("SELECT ID FROM SQLUser. Organization WHERE Name = '"_CompanyName_"'")
Do rset. Execute() //выполнение запроса

Метод Prepare - подготавливает (компилирует) запрос для выполнения, метод Execute - выполняет запрос.

Присвоение ссылки идет в теле конструкции if в блоке кода else:

set CompanyID = rset. Data("ID")
set Company = ##class(User. Organization).%OpenId(CompanyID)

Пункт 4

Пример: Если компании с указанным названием не существует, то введем с консоли по запросу город, улицу и номера, создать новый объект класса компания, вызвав соответствующий метод класса. Присвоим ссылку на компанию объекту сотрудника из п.2.

Код этой части программы выглядит следующим образом:

if 'rset. Next() //проверяем, имеет ли набор данные
{
  read !,"Введите город, где расположена компания: ",City
  read !,"Введите название улицы, где расположена компания: ",Street
  do
  {
  read !,"Введите дом-корпус-квартиру, где расположена компания: ",Numberz
  }
  while ('(Numberz?.N1"-".N1"-".N))

  set Company = ##class(User. Organization).CreateOrganization(CompanyName, City, Street, Numberz)
}
else
{
  set CompanyID = rset. Data("ID")
  set Company = ##class(User. Organization).%OpenId(CompanyID)
}
set NewWM. WorkerOrganization = Company
do NewWM.%Save()

Рассмотрим пояснения к тексту программы. Конструкция вида: 

do
{
  read !,"Введите дом-корпус-квартиру, где расположена компания: ",Numberz
}
while ('(Numberz ?.N1"-".N1"-".N))

означает, что ввод производится до тех пор, пока введенные данные не будут соответствовать шаблону ("?" - оператор соответствия шаблону).

Создаем новый объект класса "компания", вызвав соответствующий метод класса:

set Company = ##class(User. Organization).CreateOrganization(CompanyName, City, Street, Numberz)

Пояснение блока кода else смотрите выше в п.3. Присваиваем ссылку на компанию объекту сотрудника из п.2:

set NewWM. WorkerOrganization = Company

Пункт 5

Пример: Сохранить новый объект "Сотрудник" (или "Руководитель") в базе данных.

Для этого используется конструкция:

do NewWM.%Save()

Объединим все части и посмотрим листинг этой программы полностью.

Листинг программы

write !,"Завершение ввода происходит по двойному нажанию на 'Enter' ",!
for
{
  read !,"Введите имя сотрудника: ",Name
  quit:Name=""
  read !,"Введите название компании: ",CompanyName
  quit:CompanyName=""
  read !,"Введите должность: ",Post
  quit:Post=""

  if (Post="руководитель")
  {
  set NewWM = ##Class(User. Manager).%New()
  set NewWM. HireDate = $ZDateTime($Horolog,3)
  }
  else 
  {
  set NewWM = ##Class(User. Worker).%New()
  }
  set NewWM. WorkerName = Name
  set NewWM. WorkerPost = Post
  set rset = ##class(%ResultSet).%New("%DynamicQuery:SQL")
  Do rset. Prepare("SELECT ID FROM SQLUser. Organization WHERE Name = '"_CompanyName_"'")
  Do rset. Execute()
  if 'rset. Next()
  {
  read !,"Введите город, где расположена компания: ",City
  read !,"Введите название улицы, где расположена компания: ",Street
  do
  {
  read !,"Введите дом-корпус-квартиру, где расположена компания: ",Numberz
  }
  while ('(Numberz?.N1"-".N1"-".N))
  set Company = ##class(User. Organization).CreateOrganization(CompanyName, City, Street, Numberz)
  }
  else
  {
  set CompanyID = rset. Data("ID")
  set Company = ##class(User. Organization).%OpenId(CompanyID)
 }
  set NewWM. WorkerOrganization = Company
  do NewWM.%Save()
}

Теперь в среде Cache` Terminal посмотрим, как эта программа работает.

Запуск программы в в среде Cache` Terminal

Утилита Cache` Terminal может быть использована для отладки программ, процедур, функций, проверки работы отдельных операторов. Работа ведется в режиме командной строки. Утилита чрезвычайно проста. После приглашения набирается команда и нажимается ENTER. Здесь же выводится результат выполнения команды. Окно утилиты приведено ниже.

Для запуска Терминала необходимо на панели задач нажать правой кнопкой мыши на значок Cache` http://*****/metpbd/lab/create/create_html_m26c7965.png:

http://*****/metpbd/lab/create/create_html_1fdff318.png

и в выпадающем меню выбрать "Терминал":

http://*****/metpbd/lab/create/create_html_m3e39a060.png

Откроется окно утилиты, которое содержит командную строку для ввода команд и отображения результатов их выполнения. Вызов программы осуществляется с помощью команды do. После набора команды и ее параметров следует нажать Enter. В окне отобразится результат выполнения команды. Рассмотрим пример вызова созданной программы:

http://*****/metpbd/lab/create/create_html_11965a9a.png

Вид программы после запуска, запрос ввода данных:

http://*****/metpbd/lab/create/create_html_m9592b1d.png

Ввод сотрудника, должность которого НЕ руководитель. Как видно из рисунка, что ввод продолжается циклически:

http://*****/metpbd/lab/create/create_html_m5a774436.png

Ввод сотрудника, должность которого руководитель, а компания, в которой он работает, еще не введена в БД:

http://*****/metpbd/lab/create/create_html_m686bc330.png

Работа с Порталом

Для запуска "Портала" необходимо на панели задач нажать правой кнопкой мыши на значок Cache` http://*****/metpbd/lab/create/create_html_m26c7965.pngи в выпадающем меню выбрать "Портал управления системой". Главное окно Портала выглядит как:

http://*****/metpbd/lab/create/create_html_251660d7.png

В "Портале управления системой" классы и их описание можно просмотреть во вкладке "Классы":

http://*****/metpbd/lab/create/create_html_m1edade3b.png

Для просмотра описания класса следует выбрать ссылку "Документация". Описание класса на примере класса User. Organization:

http://*****/metpbd/lab/create/create_html_m65a20e14.pnghttp://*****/metpbd/lab/create/create_html_4bfe3d7e.png

Также в "Портале управления системой" можно посмотреть таблицы, которые имеются в БД. Для этого на Главной странице вместо вкладки "Классы" надо выбрать "SQL" и указать SQL схему (например, в области User):

http://*****/metpbd/lab/create/create_html_4004e066.png

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

http://*****/metpbd/lab/create/create_html_4933224e.png

Нажав на "OpenTable", можно просмотреть содержимое таблицы. Пример содержимого таблицы Worker:

http://*****/metpbd/lab/create/create_html_4c1acb30.png

Пример содержимого таблицы Organization:

http://*****/metpbd/lab/create/create_html_1d4062cd.png

Пример содержимого таблицы Manager:

http://*****/metpbd/lab/create/create_html_m1c371ffb.png

Если в меню Главной страницы перейти на ссылку "Запросы", то можно просмотреть запросы для данной схемы. Например, просмотреть те запросы, которые относятся к п.2 и п.3:

http://*****/metpbd/lab/create/create_html_2ec7e648.png

Работа с объектной базой данных

Создадим программу работы с объектами на языке Cache` Object Script в среде Cache`Studio и вызвать ее из среды Cache` Terminal. Программа принимает на вход значения:

    all — просмотр списка всех сотрудников и руководителей, director — просмотр списка всех руководителей, номер — просмотр информации о сотруднике (руководителе), ID которого указан как входной параметр.

Для получения списка ID можно использовать SQL-запрос.

Для отображения информации необходимо обращаться к объекту класса "Сотрудник", его свойствам и методам:

    "Информация о сотруднике" (класс "Сотрудник"(листинг)/ "Руководитель"(листинг), демонстрирует полиморфизм), название компании (ссылка через связанный объект класса "Компания"(листинг)), "Полный адрес" (класс "Адрес"(листинг), ссылка через связанный и встроенный объекты).

Программа для обращения к объектному представлению

По аналогии с предыдущим примером, создаем файл программы.Выбор того или иного параметра организован с помощью конструкции if:

if condition{code} elseif condition{code} else {code}

, где condition - это условие вида:

condition= <выр1>[,<выр2>,…,<выр3>].

Чтобы блок программы выполнился, все условия в списке должны быть логически истинными. В нашем конкретном случае код программы выглядит так:

main(var)
{
  if var="all"
  {
  code
  }
  elseif var="director"
  {
  code
  }
  else
  {
  code
  }
}

Далее рассмотрим по отдельности реализацию каждого условия.

Просмотр списка всех сотрудников и руководителей

Выполняется при вводе параметра "all". Рассмотрим алгоритм выполнения программы по шагам:

    Выводим на экран монитора надпись-заголовок "Список сотрудников: ". Используем объект класса % ResultSet для подготовки динамического SQL-запроса, используя метод Prepare:

set rset = ##class(%ResultSet).%New("%DynamicQuery:SQL")
Do rset. Prepare("SELECT ID FROM SQLUser. Worker")
Do rset. Execute() //выполнениезапроса

    Устанавливаем счетчик  i в ноль. Организовываем цикл while. Метод Next перемещает курсор на следующую строку данных запроса. В теле цикла идет увеличение i, присвоение ссылки полю id, а затем открытие объекта класса User. Worker с помощью идентификатора id:

set id = rset. Data("ID")
set NewWM = ##class(User. Worker).%OpenId(id)

    Вывод информации о сотруднике, используя метод WorkerInfo():

write !,i_". "_ NewWM. WorkerInfo(),

    Вывод полного адреса компании:

write !, "Адрес компании: "
write NewWM. WorkerOrganization. OrganizationAddress. FullAddress(),!

В итоге получаем следующую программу:

if var="all"
{
  write !, "Список сотрудников: "
  set rset = ##class(%ResultSet).%New("%DynamicQuery:SQL")
  Do rset. Prepare("SELECT ID FROM SQLUser. Worker")
  Do rset. Execute()
  set i = 0
  while (rset. Next())
  {
  set i = i+1
  set id = rset. Data("ID")
  set NewWM = ##class(User. Worker).%OpenId(id)
  write !,i_". "_ NewWM. WorkerInfo()
  write !, "Адрес компании: "  write NewWM. WorkerOrganization. OrganizationAddress. FullAddress(),!
  }
}

Просмотр списка всех руководителей

Выполняется при вводе параметра "director". Рассмотрим алгоритм выполнения программы по шагам:

    Выводим на экран монитора надпись-заголовок "Список руководителей: " Используем объект класса % ResultSet для подготовки динамического SQL-запроса, используя метод Prepare:

set rset = ##class(%ResultSet).%New("%DynamicQuery:SQL")
Do rset. Prepare("SELECT ID FROM SQLUser. Manager")
Do rset. Execute() //выполнение запроса
В запросе только уже выбираем ID из таблицы "Руководителей".

    Устанавливаем i в ноль. Организовываем цикл while. Метод Next перемещает курсор на следующую строку данных запроса. В теле цикла идет увеличение i, присвоение ссылки полю id, а затем открытие объекта класса User. Worker с помощью идентификатора id:

set id = rset. Data("ID")
set NewWM = ##class(User. Worker).%OpenId(id)

    Вывод информации о сотруднике, используя метод WorkerInfo():

write !,i_". "_ NewWM. WorkerInfo(),

    Вывод полного адреса компании:

write !, "Адрес компании: "
write NewWM. WorkerOrganization. OrganizationAddress. FullAddress(),!

В итоге получаем следующую программу:

elseif var="director"
{
  write !, "Список руководителей: "
  set rset = ##class(%ResultSet).%New("%DynamicQuery:SQL")
  Do rset. Prepare("SELECT ID FROM SQLUser. Manager")
  Do rset. Execute()
  set i = 0
  while (rset. Next())
  {
  set i =i+1
  set id = rset. Data("ID")
  set NewWM = ##class(User. Worker).%OpenId(id)
  write !,i_". "_ NewWM. WorkerInfo()
  write !, "Адрес компании: "  write NewWM. WorkerOrganization. OrganizationAddress. FullAddress(),!
  }
}

Просмотр информации о сотруднике (руководителе), ID которого указан как входной параметр

Рассмотрим алгоритм выполнения по шагам:

    Выводим на экран монитора надпись "Код сотрудника = …: ", где вместо "…" номер ID, который введет пользователь. Используем объект класса %ResultSet для подготовки динамического SQL-запроса, используя метод Prepare:

Set rset=##class(%ResultSet).%New("%DynamicQuery:SQL")
do rset. Prepare("SELECT * FROM SQLUser. Worker WHERE ID='"_var_"'")
do rset. Execute ()

Запрос выдает из таблицы "Сотрудник" данные того сотрудника, чей ID был введен пользователем.

    Далее по аналогии с двумя вышеперечисленными примерами организуется цикл. В результате получаем следующий код:

else
{
  write !,"Код сотрудника = "_var_":",!
  Set rset=##class(%ResultSet).%New("%DynamicQuery:SQL")
  do rset. Prepare("SELECT * FROM SQLUser. Worker WHERE  ID='"_var_"'")
  do rset. Execute() 
  while(rset. Next())
  {
  set NewWM = ##class(User. Worker).%OpenId(rset. Data("ID"))
  write !, NewWM. WorkerInfo()
  write !, "Адрес компании: "
  write NewWM. WorkerOrganization. OrganizationAddress. FullAddress(),!
  }
}

Объединим все части воедино для просмотра листинга программы полностью.

Листинг программы просмотра списка сотрудников Prog3

main(var)
{
  if var="all"
  {
    write !, "Список сотрудников: "
  set rset = ##class(%ResultSet).%New("% DynamicQuery:SQL")
  Do rset. Prepare("SELECT ID FROM SQLUser. Worker")
  Do rset. Execute()
  set i = 0
  while (rset. Next())
  {
  set i =i+1
  set id = rset. Data("ID")
  set NewWM = ##class(User. Worker).%OpenId(id)
  write !,i_". "_ NewWM. WorkerInfo()
  write !, "Адрес компании: "
  write NewWM. WorkerOrganization. OrganizationAddress. FullAddress(),!
  }
  }
  elseif var="director"
  {
  write !, "Список руководителей: "
  set rset = ##class(%ResultSet).%New("%DynamicQuery:SQL")
 Do rset. Prepare("SELECT ID FROM SQLUser. Manager")
  Do rset. Execute()
  set i = 0
  while (rset. Next())
  {
  set i =i+1
  set id = rset. Data("ID")
  set NewWM = ##class(User. Worker).%OpenId(id)
  write !,i_". "_ NewWM. WorkerInfo()
  write !, "Адрес компании: "
  write NewWM. WorkerOrganization. OrganizationAddress. FullAddress(),!
  }
  }
  else
  {
 write !,"Код сотрудника = "_var_":",!
  Set rset=##class(%ResultSet).%New("%DynamicQuery:SQL")
  do rset. Prepare("SELECT * FROM SQLUser. Worker WHERE ID='"_var_"'")
  do rset. Execute()
  while(rset. Next())
  {
  set NewWM = ##class(User. Worker).%OpenId(rset. Data("ID"))
  write !, NewWM. WorkerInfo()
  write !, "Адрес компании: "
  write NewWM. WorkerOrganization. OrganizationAddress. FullAddress(),!
  }
  }
}

Проверка работоспособности программы

Теперь посмотрим, как работает эта программа. Запустим ее в среде Cache` Terminal с различными параметрами:

http://*****/metpbd/lab/obj/obj_html_m64650b85.png

Запутим программу Prog3 с параметром "all":

http://*****/metpbd/lab/obj/obj_html_2f702b9c.png

Как и говорилось выше, сначала идет запись-заголовок "Список сотрудников". Так как в таблице БД список сотрудников достаточно большой, он здесь виден не весь. Получилось, что первые 6 сотрудников являются руководителями и только 7-й – нет. Но разница между выводом информации видна.

Запустим программу Prog3 с параметром "director":

http://*****/metpbd/lab/obj/obj_html_.png

Как видно из результата, выдалась информация только о руководителях:

http://*****/metpbd/lab/obj/obj_html_797fd913.png

Запустим программу Prog3 с параметром - номером:

http://*****/metpbd/lab/obj/obj_html_m32a33ccf.png

Результат выполнения показал, что сначала вывелось для уведомления сообщение о том, какой код сотрудника был введен, а затем – информация об этом сотруднике:

http://*****/metpbd/lab/obj/obj_html_m4813b75b.png

Работа с глобалами

Создадим в среде Cache` Studio процедуры для обращения к данным используя прямой доступ:

    Список компаний - отобразить список всех названий компаний, их сфер деятельности и городов. Удалить сотрудника - удаление записи о сотруднике.
    Входные параметры: имя сотрудника.
    Выходные параметры: сообщение о успешном удалении. Назначить руководителя - изменение записи о руководителе.
    Входные параметры: имя сотрудника, дата и время назначения.
    Выходные параметры: сообщение о успешном обновлении.

В этом случае объекты, сохраненные в базе данных, представлены как многомерные массивы (глобалы). Для уточнения существующих индексов следует использовать среду Cache` Портал (раздел Globals, пакет USER). Имена глобалов данных содержат имена классов, соответствующих им, и заканчиваются символом 'D'. (Например, глобал данных для класса Company будет называться CompanyD.)

Исходные данные

Созданые классы:

    Компания, Адрес, Сотрудник, руководитель.

Ниже приведены листинги этих классов на языке Cache` Object Script.

Листинг класса Компания

Class pany Extends %Persistent // Создается хранимый класс
{
Property Name As %String [ Required ];
Index NameID On Name [ Unique ];
Property Business As list Of %String;
Property Address As Address;

// Описание метода класса, который создает новый объект класса Company
ClassMethod Create(Name As %String, city As %String, street As %String, building As %String, corps As %String, apart As %String) As Company [ SqlProc ]
{
  set new = ##class(Company).%New()
  set new. Name = Name
  set new. Address. City = city
  set new. Address. Street = street
  set new. Address. Building = building
  set new. Address. Corps = corps
  set new. Address. Apart = apart
  set done=new.%Save()
 quit new
}
}

Листинг класса Адрес

Class Lab1.Address Extends %SerialObject //Создается встроенный класс.
{
Property City As %String;
Property Street As %String;
Property Building As %String;
Property Corps As %String;
Property Apart As %String;

// Описание метода экземпляра класса, который возвращает адрес в виде строки
Method Address() As %String
{
  set retStr = $CASE(##this. City, "":"", :"г." _ ##this. City) _
  $CASE(##this. Street, "":"", :", ул." _ ##this. Street) _
  $CASE(##this. Building, "":"", :", д." _ ##this. Building) _
  $CASE(##this. Corps, "":"", :", корп." _ ##this. Corps) _
  $CASE(##this. Apart, "":"", :", кв." _ ##this. Apart)
  quit retStr
}
}

Листинг класса Сотрудник

Class Lab1.Worker Extends %Persistent // Создание хранимого класса
{
Property Name As %String [ Required ];
Property WorkPlace As Company [ Required ];
Property WorkPosition As %String;

// Метод экземпляра класса, возвращающий значения полей в виде строки
Method Info() As %String
{
  set retStr = ##this. Name _ " " _ ##this. WorkPlace. Name _ " " _ ##this. WorkPosition_" "
  quit retStr
}
}

Листинг класса руководитель

Class Lab1.Head Extends Lab1.Worker // Описание дочернего класса
{
Property ADate As %Date [ Required ];

// Переопределенный метод экземпляра класса, возвращающий значения полей в виде строки
Method Info() As %String
{
  set retStr = ##this. Name _ " " _ ##this. WorkPlace. Name _ " Руководитель(" _ $ZDATE(##this. ADate,4)_")"
  quit retStr
}
}

Структура и содержание таблиц базы данных

После компиляции классов можно посмотреть их структуру в среде Cache` Портал и убедиться, что создание и компиляция новых классов прошли успешно. Структура классов должна быть похожа на представленную ниже. Обратите внимание, что класс "Адрес" входит в состав таблицы для класса "Компания", поскольку он встроенный. Для хранимых классов создаются отдельные таблицы.

Структура таблицы "Company":

http://*****/metpbd/lab/glob/glob_html_m7909c091.png

Структура таблицы "Worker":

http://*****/metpbd/lab/glob/glob_html_m76f5f26c.png

Структура таблицы "Head":

http://*****/metpbd/lab/glob/glob_html_m461a97bc.png

Содержание таблиц базы данных

Была написана программа (листинг программы) для создания и сохранения в базе данных новых объектов. После выполнения этой программы в среде Cache` Terminal в базе данных будут содержаться некоторые объекты. Содержимое таблиц можно посмотреть в среде Cache` Портал. Содержимое таблиц должно быть аналогично представленному ниже.

Записи таблицы "Company":

http://*****/metpbd/lab/glob/glob_html_56da688c.png

Записи таблицы "Worker":

http://*****/metpbd/lab/glob/glob_html_1f7f6468.png

Записи таблицы "Head":

http://*****/metpbd/lab/glob/glob_html_m25b4875a.png

Сохранение объектов в глобалах

Для внутреннего хранения объектов используются глобалы. Глобал - это многомерный массив, который хранится в виде разреженных матриц.

Каждый хранимый класс может сохранять свои экземпляры внутри базы данных, используя один или несколько узлов многомерных данных (глобалей). При создании класса компилятором класса автоматически создаются определения двух глобалей: глобали данных и индексной глобали. При этом справедливо следующее:

    Данные сохраняются в глобале, имя которого начинается с полного имени класса, т. е. пакет. класс, при этом справа к имени глобала данных добавляется буква "D", к имени глобала индекса добавляется буква "I". Данные каждого экземпляра сохраняются внутри единственного узла глобала данных, при этом значения свойств размещаются в списковых структурах. Каждый узел глобала данных имеет объектный идентификатор ID. По умолчанию, значения ID - это целые числа, значения которых обеспечиваются вызовом функции инкемента. Первый элемент списковой структуры, хранимой в каждом узле, пустой. Это зарезервировано для имени подкласса. Если определить подклассы, то этот элемент будет содержать имя подкласса. Метод %OpenId использует эту информацию для полиморфного открытия корректного типа объекта, когда несколько объектов сохраняются внутри подобных экстентов.

Рассмотрим глобалы, созданные для наших классов, и их содержимое.

Просмотр глобалов в среде Cache` Портал

Для запуска "Портала" необходимо на панели задач нажать правой кнопкой мыши на значок Cache` http://*****/metpbd/lab/create/create_html_m26c7965.pngи в выпадающем меню выбрать "Портал управления системой". Главное окно Портала выглядит как:

http://*****/metpbd/lab/create/create_html_251660d7.png

Затем перейти на "Глобалы",чтобы увидеть те, которые присутствуют в БД:

Имя

Расположение

Сохранять

Коллаж

lt

d:\programmes\cache\mgr\user\

Нет

Cyrillic1

Отображение

Редактировать

mcq

d:\programmes\cache\mgr\user\

Нет

Cyrillic1

Отображение

Редактировать

mqh

d:\programmes\cache\mgr\user\

Нет

Cyrillic1

Отображение

Редактировать

panyD

d:\programmes\cache\mgr\user\

Нет

Cyrillic1

Отображение

Редактировать

panyI

d:\programmes\cache\mgr\user\

Нет

Cyrillic1

Отображение

Редактировать

User. WorkerD

d:\programmes\cache\mgr\user\

Нет

Cyrillic1

Отображение

Редактировать

Для просмотра содержимого конкретного глобала следует выбрать ссылку "Отображение". Рассмотрим глобалы данных, определенные для наших классов.

Глобал данных для классов "Компания" и "Адрес"

Экземпляры класса "Компания" (листинг класса) и встроенного в него класса "Адрес" (листинг класса), которым соответствует таблица Company (содержимое таблицы), хранится в виде глобала CompanyD:

http://*****/metpbd/lab/glob/glob_html_m78c89d72.png

Рассмотрим структуру глобала:

^Lab1.CompanyD - последний индекс экземпляра записи. В глобале CompanyD последней записью является 5-ая запись.

^Lab1.CompanyD(5) – 5-я запись, экземпляр класса с индексом 5. Содержит список свойств экземпляра $lb("",$lb("","4","Moscow","1","Bauman"),"","BMSTU"), что означает:

"" - пустое поле, зарезервировано для производных классов, $lb("","4","Moscow","1","Bauman") - список, содержащий поля встроенного класса "Адрес" (листинг класса). Состоит из полей: квартира "", дом "4", город "Moscow", корпус "1", улица "Bauman". Поля встроенного класса расположены по алфавиту. "" - пустой список сфер деятельности. "BMSTU" - название компании.

Глобал данных для классов "Сотрудник" и "Руководитель"

Экземпляры классов "Сотрудник" (листинг класса) и "Руководитель" (листинг класса), которым соответствуют таблицы Worker (содержимое таблицы) и Head (содержимое таблицы), храниятся в виде одного глобала WorkerD:

http://*****/metpbd/lab/glob/glob_html_33aa9367.png

Рассмотрим структуру глобала:

^Lab1.WorkerD - последний индекс экземпляра записи. В данном случае это 14.

^Lab1.WorkerDя запись, экземпляр класса с индексом 8. Содержит список свойств экземпляра, $Lb("~Lab1.head~","Name4",,"4","руководитель"), что означает:

"~Lab1.head~" - название производного класса, к которому относится объект. Для объекта базового класса это поле было бы пустым. "Name4" - Имя сотрудника. "4" - ID объекта класса "Компания"- место работы (ссылка на связанный объект). "руководитель" - должность.

^Lab1.WorkerD(8,"head") - список данных, относящихся к производному классу. 8 - индекс объекта базового класса, где хранятся свойства базового класса. "head" - название производного класса. Содержит $Lb(,,60632), что означает:

60632 - дата назначения, значение даты в формате zdate.

Таблицы Worker и Head находятся в глобале WorkerD. Различия в записи: Worker записывается с указанием порядкового номера (WorkerD(1)=$Lb(…)), а Head – с указанием номера и поля со значением "head" (WorkerD(1,"head")=$Lb(…)).

Программа для работы с глобалами

Используя функции для работы с глобалами, составим программу на языке Cache` Object Script в среде Cache` Studio. Рассмотрим основные шаги алгоритма. Сначала отобразим меню программы для выбора действия:

set action = 0
while '((action=1)!(action=2)!(action=3)!(action=""))
{
read!,"Список компаний(1)/Удалить сотрудника(2)/Назначить руков.(3): ",action
}
if (action="") quit

Составить список компаний

Если была выбрана функция отображения, то выполним следующие действия. Организуем в цикле поиск значений глобала CompanyD, (в CompanyD находится номер последней записи):

For i=1:1:^Lab1.CompanyD

По каждому экземпляру проверим, что он существует:

if ($Data(^Lab1.CompanyD(i))>0)

Если да, то выполним вывод названия компании ( 4-ой позиции текущей записи):

write "/",$List(^Lab1.CompanyD(i),4)

Вывод адреса (всех элементов списка, хранящегося во 2-ой позиции текущей записи):
for k=1:1:$ListLength($List(^Lab1.CompanyD(i),2))

{ write $List($List(^Lab1.CompanyD(i),2),k)," " }

Вывод сфер деятельности (всех элементов списка, хранящегося 3-ей позиции текущей записи):

for j=1:1:$ListLength($List(^Lab1.CompanyD(i),3))

{ write $List($List(^Lab1.CompanyD(i),3),j)," " }

В итоге получаем код:

// Список компаний
if (action=1)
{
  For i=1:1:^Lab1.CompanyD
  {
  write!,$Data(^Lab1.CompanyD(i))
  if ($Data(^Lab1.CompanyD(i))>0) // Проверка на ненулевое содержание. 
 {
  // Вывод названия компании ( 4 ой позиции текущей записи)
  write "/",$List(^Lab1.CompanyD(i),4)
  // Вывод адреса (всех элементов списка, хранящегося во 2-ой позиции текущей записи)
  for k=1:1:$ListLength($List(^Lab1.CompanyD(i),2))
  {
  write $List($List(^Lab1.CompanyD(i),2),k)," "
  } 
 write "/"
// Вывод сфер деятельности (всех элементов списка, хранящегося 3-ей позиции текущей записи
  for j=1:1:$ListLength($List(^Lab1.CompanyD(i),3))
  {
  write $List($List(^Lab1.CompanyD(i),3),j)," "
  } 
   }
 }
}

Удалить сотрудника (руководителя)

Если была выбрана функция удаления, то выполним следующие действия. Запросим имя сотрудника:

read!,"Имя сотрудника: ",WName

Выполним в цикле поиск записей глобала WorkerD (в WorkerD хранится номер последней записи):

for i=1:1:^Lab1.WorkerD

Проверим на ненулевое значение записи и выполним поиск по имени (2-ая позиция):

if (($Data(^Lab1.WorkerD(i)))&&($List(^Lab1.WorkerD(i),2)=WName))

Если запись - искомая, то удалим ее. Для получения доступа к элементу списка после номера записи указывается номер по списку. При удалении индекса удаляются и вложенные глобала, поэтому достаточно удалить сотрудника, руководитель удалится автоматически:

kill ^Lab1.WorkerD(i)

В итоге получаем код:

// Удаление сотрудника
if (action=2)
{
  set Found=0
  read!,"Имя сотрудника: ",WName
// Поиск записей глобала WorkerD (в WorkerD хранится номер последней записи)
  for i=1:1:^Lab1.WorkerD 
  {
// Проверка на ненулевое значение записи и поиск по имени (2-ая позиция)
  if (($Data(^Lab1.WorkerD(i)))&&($List(^Lab1.WorkerD(i),2)=WName))
// Для получения доступа к элементу списка после номера записи указывается номер по списку.
  {
  kill ^Lab1.WorkerD(i) // Удаление текущей записи
  set Found=1
  write!,"Запись удалена!"
  }
  }
  if (Found=0)
  {
  write!,"Данный сотрудник отсутствует"
  }
}

Назначение руководителя

Если была выбрана функция назначения, то выполним следующие действия. Введем имя руководителя и дату назначения (с проверкой правильности ввода):

read!,"Имя руководителя: ",HName
read!,"Дата назначения(чч/мм/гггг): ",ADate
while '($ZDATEH(ADate,5))
{
read!,"Дата назначения(чч/мм/гггг): ",ADate
}

Выполним в цикле поиск записей глобала WorkerD (в WorkerD хранится номер последней записи):

for i=1:1:^Lab1.WorkerD

Проверим на ненулевое значение записи:

if ($Data(^Lab1.WorkerD(i)))

Выполним поиск значений записей, которые совпадают с искомыми значениями:

if (($Data(^Lab1.WorkerD(i,"Head")))&&($List(^Lab1.WorkerD(i),2)=HName))

Для совпадающих записей выполним: задание должности (значение для 5-ой позиции текущей записи глобала) :

set $List(^Lab1.WorkerD(i),5)="руководитель"

Задание даты (значение для 3-ей позиции текущей записи глобала):

set $List(^Lab1.WorkerD(i,"Head"),3)=$ZDATEH(ADate,5)

Создадим запись для производного класса (1-ая позиция записи) Head:

set $List(^Lab1.WorkerD(i),1)="~Lab1.Head~"

Измененим должность (запись в 5-ой позиции):

set $List(^Lab1.WorkerD(i),5)="руководитель"

Создадим запись в таблице Head с заданием даты. Для этого используется запись (i,"Head"), где i - номер записи. Используется ф-ия ListBuild:

set ^Lab1.WorkerD(i,"Head")=$ListBuild(,,$ZDATEH(ADate,5))

В итоге получаем код:

//----
//Назначение руководителя
if (action=3)
{
  read !,"Имя руководителя: ",HName
  read !,"Дата назначения(чч/мм/гггг): ",ADate
  while '($ZDATEH(ADate,5))
  {
  read!,"Дата назначения(чч/мм/гггг): ",ADate
  }
  for i=1:1:^Lab1.WorkerD // Поиск записей глобала WorkerD
  {
  if ($Data(^Lab1.WorkerD(i))) // Проверка на ненулевое значение записи
  {
// Поиск значений записей, которые совпадают с искомыми значениями
  if (($Data(^Lab1.WorkerD(i,"Head")))&&($List(^Lab1.WorkerD(i),2)=HName))
  {
// Задание должности (значение для 5-ой позиции текущей записи глобала)
  set $List(^Lab1.WorkerD(i),5)="руководитель"
// Задание даты (значение для 3-ей позиции текущей записи глобала)
  set $List(^Lab1.WorkerD(i,"Head"),3)=$ZDATEH(ADate,5)
  write !,"Запись руководителя изменена!"
  }
  if ($List(^Lab1.WorkerD(i),2)=HName) // Поиск имени (2-ая позиция)
  {
// Создание записи для связного класса (1-ая позиция записи) Head
  set $List(^Lab1.WorkerD(i),1)="~Lab1.Head~"
// Изменение должности (запись в 5-ой позиции)
  set $List(^Lab1.WorkerD(i),5)="руководитель"
// Создание записи в таблице Head с заданием даты. Для этого используется запись (i,"Head"), где i - номер записи. Используется ф-ия ListBuild
  set ^Lab1.WorkerD(i,"Head")=$ListBuild(,,$ZDATEH(ADate,5))
  write!,"Запись изменена!"
  }
  }
  }
}

Листинг программы работы с глобалами

for
{
// Меню программы
set action = 0
while '((action=1)!(action=2)!(action=3)!(action=""))
{
  read!,"Список компаний(1)/Удалить сотрудника(2)/Назначить руков.(3): ",action
}
if (action="") quit

//----
//Список компаний
if (action=1)
{
// Поиск значений глобала CompanyD
// (в CompanyD находится номер последней записи)
For i=1:1:^Lab1.CompanyD
{
  write!,$Data(^Lab1.CompanyD(i))
  if ($Data(^Lab1.CompanyD(i))>0) // Проверка на ненулевое содержание.
  {
// Вывод названия компании ( 4 ой позиции текущей записи)
  write "/",$List(^Lab1.CompanyD(i),4)
// Вывод адреса (всех элементов списка, хранящегося во. // 2-ой позиции текущей записи)
  for k=1:1:$ListLength($List(^Lab1.CompanyD(i),2))
  {
  write $List($List(^Lab1.CompanyD(i),2),k)," "
  }
  write "/"
// Вывод сфер деятельности (всех элементов
//списка, хранящегося 3-ей позиции текущей записи
  for j=1:1:$ListLength($List(^Lab1.CompanyD(i),3))
  {
  write $List($List(^Lab1.CompanyD(i),3),j)," "} }
  }
  }
//----
//Удаление сотрудника
if (action=2)
{
  set Found=0
  read!,"Имя сотрудника: ",WName
// Поиск записей глобала WorkerD (в WorkerD хранится номер последней записи)
  for i=1:1:^Lab1.WorkerD
// Проверка на ненулевое значение записи и поиск по имени (2-ая позиция)
  if (($Data(^Lab1.WorkerD(i)))&&($List(^Lab1.WorkerD(i),2)=WName))
/ Для получения доступа к элементу списка после номера записи указывается номер по списку.
  {
  kill ^Lab1.WorkerD(i) // Удаление текущей записи
  set Found=1
  write!,"Запись удалена!"
  }
}
if (Found=0) {write !,"Данный сотрудник отсутствует"}
}
//----
//Назначение руководителя
if (action=3)
{
  read!,"Имя руководителя: ",HName
  read!,"Дата назначения(чч/мм/гггг): ",ADate
  while '($ZDATEH(ADate,5))
  {
  read!,"Дата назначения(чч/мм/гггг): ",ADate
  }
  for i=1:1:^Lab1.WorkerD // Поиск записей глобала WorkerD
  {
  if ($Data(^Lab1.WorkerD(i))) // Проверка на ненулевое значение записи
  {
// Поиск значений записей, которые совпадают с искомыми значениями
  if (($Data(^Lab1.WorkerD(i,"Head")))&&($List(^Lab1.WorkerD(i),2)=HName))
  {
// Задание должности (значение для 5-ой позиции текущей записи глобала)
  set $List(^Lab1.WorkerD(i),5)="руководитель"
// Задание даты (значение для 3-ей позиции текущей записи глобала) 
  set $List(^Lab1.WorkerD(i,"Head"),3)=$ZDATEH(ADate,5)
  write!,"Запись руководителя изменена!"
  }
  if ($List(^Lab1.WorkerD(i),2)=HName) // Поиск имени (2-ая позиция)
  {
// Создание записи для связного класса (1-ая позиция записи) Head
  set $List(^Lab1.WorkerD(i),1)="~Lab1.Head~"
// Изменение должности (запись в 5-ой позиции)
  set $List(^Lab1.WorkerD(i),5)="руководитель"
// Создание записи в таблице Head с заданием даты. Для этого используется запись (i,"Head"), где i - номер записи. Используется ф-ия ListBuild (см. приложение)
  set ^Lab1.WorkerD(i,"Head")=$ListBuild(,,$ZDATEH(ADate,5))
  write!,"Запись изменена!"
  }
  }
  }
}

Экспорт/ Импорт глобалов

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

Для проведения экспорта необходимо зайти в Портал управления системой: [Домашняя страница] > [Глобалы] > [Экспорт глобалов]. Выбрать глобалы, которые необходимо экспортировать:

http://*****/metpbd/lab/glob/glob_html_m747adcc2.png

Результат выполнения:

http://*****/metpbd/lab/glob/glob_html_m3f708a75.png

Для импорта глобалов необходимо зайти в Портал управления системой: [Домашняя страница] > [Глобалы] > [Импорт глобалов]. Выбрать файл, из которого необходимо импортировать глобалы:

http://*****/metpbd/lab/glob/glob_html_m55ca582e.png

Результат выполнения:

http://*****/metpbd/lab/glob/glob_html_2bd4e88d.png

В случае удачного импорта появится сообщение:

http://*****/metpbd/lab/glob/glob_html_26ba3fd2.png

Список используемой литературы.

1.  «Постреляционная СУБД Cache» - http://www. *****/database/articles/cache. shtml

2.  «Взаимодействие СУБД Cache с внешним миром» - http://www. *****/database/cache/cache_ex/

3.  СУБД Cache. Объектно - ориентированная разработка приложений. Учебный курс [В. Кирстен, М. Ирингер, Б. Рериг, П. Шульте]