Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
19
Добавлен:
18.06.2017
Размер:
882.7 Кб
Скачать

USER>kill var1 USER>write

kill без аргументов удаляет все локальные переменные для активного процесса.

Теперь определим скалярную глобаль:

USER>set ^var1=”abc” USER>write

Write без аргументов выводит только локальные переменные, однако если указать имя глобали, то write выведет ее значение:

USER>write ^var1 abc

С помощью kill можно удалить глобаль, если полностью указать ее имя:

USER>kill ^var1

Многомерные локальные переменные и глобали определяются следующим образом:

USER>set var1("abc",123)=1 USER>set ^var2("abc",123)=1

Для многомерных переменных также применима функция kill.

Полезной функцией при работе с переменными является функция $Data(переменная). С помощью этой функции можно определить, существует переменная или нет. Результатом могут быть следующие значения: 0 или 10 – переменная с данными индексами не существует; 1 или 11– переменная существует и содержит данные. Пример,

USER>kill USER>set a=10 USER>write $D(a) 1

USER>set ^a(1,"abc")=1 USER>write $Data(^a) 10

USER>write $Data(c) 0

USER>set ^a(1,"abc","def")=1 USER>write $Data(^a(1,"abc")) 11

Другой полезной функцией является $Get(переменная, Х). При существовании переменной возвращается ее значение, иначе возвращается Х.

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

^Пакет.КлассD – для хранения данных;

^Пакет.КлассI – для хранения индексов: ^Пакет.КлассS – для хранения BLOB и CLOB.

С помощью утилиты Caché Explorer можно получить прямой доступ к многомерным структурам ядра БД Caché. Caché Explorer предоставляет пользователю ряд функций, включающий функции просмотра, удаления и редактирования элементов структур, а также функции импорта, экспорта глобалей, программ и классов Caché и многие другие функции. Внешний вид утилиты приведен на рис.7.

21

Рис.7. Caché Explorer

Каждой области (namespace) соответствуют 3 вложенные папки: папка Глобали, папка Программы и папка Классы. Каждая из этих папок содержит соответственно список глобалей (или глобальных переменных), список классов и список программ, относящихся к выбранной области. Нажатие правой кнопки мыши на одном из элементов списков вызывает контекстное меню, с функциями редактирования, импорта/экспорта и многими другими.

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

До сих пор мы изучали изменение состояния объектов, т.е. изменение значений свойств экземпляров. Однако, объект обладает не только состоянием, но и поведением.

Определим функции системы и реализуем их с помощью методов классов и объектов. Необходимо понимать разницу между методами классов и методами объектов. Методы объекта или экземпляра всегда вызываются для определенного экземпляра класса, ссылку на который они неявно получают. В противоположность методам экземпляра, методы класса не вызываются для определенного экземпляра и не имеют доступа к свойствам или методам экземпляров, однако имеют доступ к параметрам классов. Характерным примером метода класса является метод %New(), который не применим к экземпляру класса, т.к. порождает его.

Метод объекта как и метод класса, обладает однозначным именем и списком формальных аргументов. Используя формальные аргументы и алгоритм, реализуемый кодом метода, метод возвращает однозначное значение заданного типа.

Вобъектной модели Caché реализованы четыре разновидности методов:

Метод-код;

Метод-выражение;

Метод-вызов;

22

Генератор методов.

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

Метод-код содержит код, написанный на COS или Caché BASIC, который при компиляции преобразуется в программу Caché. Созданная программа вызывается каждый раз при обращении к методу класса или методу объекта.

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

Изучим основные структурные элементы и функции языка COS, а также принципы работы с методами на примере реализации функциональных требований предметной области «Семья».

План работы:

1.Открытие проекта Caché.

2.Использование мастера методов для создания метода РассчитатьВозраст(CalculateAge) класса Человек (Human).

3.Создание оставшихся методов используя Caché Studio.

4.Примеры использование методов в Caché Terminal.

Открытие проекта Caché.

Запустите Caché Studio. После успешного прохождения процедуры авторизации необходимо выбрать пункт меню File->Open Project или нажать комбинацию клавиш Ctrl+Shift+O. В появившемся окне открытие/создание проекта (см. рис. 8)необходимо выбрать имя соединения (Local), область (User), имя проекта (Family) и нажать кнопку ОК. Выбранный проект загружается в область Caché Studio, и можно приступать к реализации функциональной части классов.

23

Рис.8. Окно открытия проекта.

Создадим метод CalculateAge класса Family.Human с помощью мастера методов. В области проекта выбираем папку Классы, пакет Family и класс Human. Запустить мастер методов можно либо выбрав пункт меню Class->Add- >New Method, либо нажав на следующую иконку:

Первый шаг мастера методов определяет общие данные о создаваемом методе – имя метода (CalculateAge) и комментарии (Рассчитать возраст человека).

С помощью следующего шага можно определить тип возвращаемых методом данных (%Integer), а также список формальных параметров (отсутствуют).

Характеристики метода определяются на третьем шаге мастера методов. Методы типа Private могут быть вызваны только из других методов экземпляра или методов класса. Методы типа Final не могут быть переопределены в классах-наследниках. Метод класса определяется выставлением флажка Class Method. Метод класса также может быть представлен в реляционном таблицах, как хранимая процедура (SQL Stored Procedure). Создаваемый метод является общедоступным методом экземпляра, поэтому не выставляем никаких флажков и переходим на следующий шаг.

24

Код метода определяется на следующем шаге. Особенностью написания Caché программ или методов является то, что первый символ в каждой строке определяет начало имени метки внутри кода. Поэтому, код метода должен начинаться со второго символа, если это не метка. Рассчитаем возраст человека по следующей формуле: quit $H-..DofB\365. $H – это системная функция, возвращающая системную дату и время в виде двух чисел, разделенных запятой. Первое число определяет количество дней, прошедших с 31.12.1840. Второе число хранит количество секунд, прошедших с 00.00. С помощью конструкции ..DofB мы обращаемся к свойству экземпляра, из которого вызывается метод CalculateAge. Обратный слеш (\) – это оператор COS, служащий для деления без остатка. С помощью команды quit выходим из метода и возвращаем значение метода, определяемое аргументом quit. Вводим код метода в окно мастера методов и завершаем работу мастера, нажатием кнопки Finish.

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

В табл.2. приведено описание методов, которые необходимо создать самостоятельно.

Характеристики метода

Значение

Код метода и описание

Класс

Family.Baby

w !,"------------------------------"

 

 

w !,"ФИО ребенка:"_..Personal.FIO

Название

FormatData

 

 

w !,"Дата рождения:"_..Personal.DofB

Комментарий

Форматирование

w !,"Возраст:"_..Personal.CalculateAge()

 

данных

w !,"Паспорт:"_..Personal.Passport

Аргументы

Нет

w !,"Пол:"_..Personal.Sex

Тип возвращаемого значения

%Boolean

w !,"Усыновлен:"_$s(..Adopt=1:"да",1:"нет")

 

 

w !,"------------------------------"

Параметры

Нет

quit 1

Комментарии

w{rite}-вывод строки

символов на текущее устройство, ! –

 

перевод строки и возврат каретки (CRLF),

 

..Property – значение свойства активного экземпляра,

 

$s(cond1:value1,cond2:value2, 1:defaultvalue)

 

многозначное условие - если cond1=1, то вернуть value1 и

 

т.д.

 

 

quit 1 – возвращаемое значение

 

 

 

Класс

Family.Witness

w !,"------------------------------"

Название

FormatData

w !,"ФИО свидетеля:"_..Personal.FIO

 

 

w !,"Дата рождения:"_..Personal.DofB

Комментарий

Форматирование

w !,"Возраст:"_..Personal.CalculateAge()

 

данных

w !,"Паспортные данные:"_..Personal.Passport

Аргументы

Нет

w !,"Пол:"_..Personal.Sex

 

 

w !,"Адрес:"_..Address.Read(100)

Тип возвращаемого значения

%Boolean

 

 

w !,"Отношение:"_..Related

Параметры

Нет

w !,"------------------------------"

 

 

quit 1

Комментарии

..Address.Read- метод

класса %AbstactStream,

 

считывающий заданное количество символом из BLOB

 

 

 

Класс

Family.Family

n child

 

 

s child=##Class(Family.Baby).%New()

Название

AddChild

 

 

if child=$$$NULLOREF w !,"Error.New" quit 0

Комментарий

Добавление

s child.Personal.FIO=FIO

 

ребенка

 

25

Аргументы

FIO - %String,

s:DofB'="" child.Personal.DofB=DofB

 

DofB - %Date,

s child.Personal.Passport=Passport

 

Passport - %String,

s child.Personal.Sex=Sex

 

s child.Adopt=Adopt

 

Sex - %Boolean,

 

s child.Parent=cl

 

Adopt - %Boolean

if '+child.%Save() w !,"Error.Save" quit 0

Тип возвращаемого значения

%Boolean

if '+child.%Close() w !,"Error.Close" quit 0

 

 

quit 1

Параметры

Нет

 

Комментарии

n{ew}- Создание

локальной переменной для метода,

 

предыдущее значение сохраняется и восстанавливается

 

после выхода из метода. Каждая локальная переменная

 

метода должна быть инициализирована с помощью new.

 

Причина - локальные переменные методов могут

 

перекрывать друг друга, т.к. порождены в одном процессе.

 

If <expr>[,<expr>…]{code} – Условная конструкция.

 

ElseIf <expr> {code}

 

Else {code}

 

 

‘ – отрицание.

 

 

$$$NULLOREF – макрос, автоматически заменяется при

 

компиляции некоторым значением. Используется для

 

определения правильности создания экземпляра класса в

 

памяти. Системная библиотека макросов %occInclude.

 

s{et}:<expr> - предусловие, оператор set выполнится

 

только в случае истинного значения <expr>. Применимо

 

для некоторых операторов COS – write, quit и т.д.

 

+child.%Save()-преобразование типа данных. child.%Save()

 

возвращает строку – это либо 1, в случае успешного

 

завершения, либо «0 код ошибки» в случае ошибки.

 

Операция сложения (+) применяется исключительно к

 

числовым значениям, поэтому происходит преобразование

 

строки в число, при этом берутся все числа до первого

 

символа. Тоже происходит и с +child.%Close().

 

 

 

Класс

Family.Family

n i

Название

DisplayChildren

for i=1:1:..Children.Count() {

 

 

w !,"Номер - ",i

Комментарий

Вывод

d ..Children.GetAt(i).FormatData()

 

информации о

}

 

детях

quit 1

Аргументы

Нет

 

Тип возвращаемого значения

%Boolean

 

Параметры

Нет

 

Комментарии

..Children.Count()-

метод класса %RelationshipObject,

 

возвращающий количество зависимых объектов в

 

отношении.

 

 

..Children.GetAt(i) – метод класса %RelationshipObject,

 

возвращающий ссылку (OREF) на i-элемент в коллекции.

 

 

 

Класс

Family.Family

n number

Название

DeleteChild

if ..Children.Count() {

 

 

d ..DisplayChildren()

Комментарий

Удаление данных

w !,"Введите номер удаляемого ребенка (0-

 

о ребенке

отмена):"

Аргументы

Нет

r number

26

Тип возвращаемого значения

 

%Boolean

 

if number=0 quit 1

 

 

 

 

 

 

 

d ..Children.RemoveAt(number)

 

Параметры

 

Нет

 

 

 

 

 

} else {

 

 

 

 

 

 

 

w !,"***Детей нет***"

 

 

 

 

 

 

}

 

 

 

 

 

 

 

quit 1

 

 

 

Комментарии

d ..DisplayChildren()

- вызов метода активного экземпляра.

 

r{ead} number – считать строку с текущего устройства и

 

поместить в переменную number.

 

 

 

 

d

..Children.RemoveAt(number)

метод

класса

 

%RelationshipObject. Удаляет элемент на numberпозиции

 

из коллекции.

 

 

 

 

 

 

 

 

 

 

Таблица 2.

После добавления методов классы необходимо сохранять и

компилировать.

 

 

 

 

 

 

 

Примеры использования созданных методов:

 

 

 

USER>s cl=##Class(Family.Family).%New()

 

 

 

 

USER>s cl.Father.FIO="Иванов Иван Иванович"

 

 

 

USER>s cl.Mother.FIO="Иванова Любовь Владимировна "

 

 

 

USER>d cl.AddChild("Иванов Петр Иванович",+$h,"Паспорт")

 

 

USER>d cl.DisplayChildren()

 

 

 

 

Номер - 1

 

 

 

 

 

 

 

------------------------------

 

 

 

 

 

 

ФИО ребенка:Иванов Петр Иванович

 

 

 

 

Дата рождения:08/31/2001

 

 

 

 

 

 

Возраст:0

 

 

 

 

 

 

 

Паспортные данные:Паспорт

 

 

 

 

Пол:1

 

 

 

 

 

 

 

Усыновлен:нет

 

 

 

 

 

 

 

------------------------------

 

 

 

 

 

 

USER>d cl.DeleteChild()

 

 

 

 

 

 

Номер - 1

 

 

 

 

 

 

 

------------------------------

 

 

 

 

 

 

ФИО ребенка:Иванов Петр Иванович

 

 

 

 

Дата рождения:08/31/2001

 

 

 

 

 

 

Возраст:0

 

 

 

 

 

 

 

Паспортные данные:Паспорт

 

 

 

 

Пол:1

 

 

 

 

 

 

 

Усыновлен:нет

 

 

 

 

 

 

 

------------------------------

 

 

 

 

 

 

Введите номер удаляемого ребенка (0-отмена):1

 

 

 

USER>d cl.DeleteChild()

 

 

 

 

 

 

***Детей нет***

 

 

 

 

 

 

 

USER>d cl.%Save()

 

 

 

 

 

 

 

USER>d cl.%Close()

 

 

 

 

 

 

 

Использование SQL и Dynamic SQL.

Как было сказано ранее Caché хранит данные в виде многомерных структур и позволяет представлять данные в виде реляционных таблиц. Caché поддерживает все элементы ANSI-стандартов, существующие для SQL и SQL92. Обращаясь через предоставленные ODBC/JDBC драйвера к БД Caché можно запрашивать данные, удовлетворяющие некоторым условиям (DQL),

27

манипулировать данными (DML), либо создавать новые или изменять существующие таблицы (DDL).

На примерах изучим принципы работы с данными Caché используя конструкции SQL.

Для начала необходимо создать учетную запись ODBC драйвера. Во время инсталляции Caché автоматически создаются две учетных записи – для области USER и области SAMPLES. Если необходимо создать новую учетную запись, то вызывается ODBC менеджер (odbcad32) и проходится стандартная процедура создания учетной записи, используя драйвер InterSystems ODBC.

Используя любой SQL-клиент (например, WinSQL) создадим новый класс

Caché:

create table SQLTable (Prop1 %String, Prop2 %Integer)

Создадим новую запись в созданной таблице:

insert into SQLTable(Prop1,Prop2) values (“Some String”,1234)

Теперь запросим данные из таблицы SQLTable: select * from SQLTable

Как видно из примера работать с данными из Caché можно точно также, как и с данными из реляционных БД.

Кроме внешнего SQL интерфейса, в Caché программах можно использовать встроенный SQL и создавать динамические запросы. Встроенный SQL не будет часто использоваться в разрабатываемых проектах, поэтому оставляется на самостоятельное изучение.

Рассмотрим подробнее принципы работы динамических запросов, а также область их применения. OID объектов, по умолчанию, является автоинкрементальным полем и иногда возникают трудности нахождения определенного OID объекта или создания списка OID некоторого класса, удовлетворяющих некоторым критериям. Для решения подобных задач можно воспользоваться методами системного класса %ResultSet, с помощью которых можно создавать динамические запросы. Рассмотрим создание динамического запроса, для получения OID объектов класса Family.Family :

Создаем экземпляр класса %ResultSet и аргументом метода %New определяем динамический запрос:

Set result=#Class(%ResultSet) .%New(“%DynamicQuery:SQL”)

Далее, аргументом метода Prepare() задаем SQL запрос:

Do result.Prepare(“Select ID from Family.Family”)

Затем, выполняем SQL запрос методом Execute():

Do result.Execute()

В памяти создается структура данных типа список, к элементам которой необходимо обращаться используя методы Next() и Get(ИмяПоляSQLЗапроса):

For Quit:’result.Next() { Write result.Get(“ID”)

}

Do result.%Close()

Для получение полной документации о методах класса %ResultSet, а также способах создания динамических запросов, обращайтесь к документации класса

%ResultSet.

Обработка ошибок в COS.

Бывают случаи, когда необходимо обработать ошибку, возникшую в случае непредвиденных обстоятельств. Например, операция w 1/I, при отсутствии проверки I на равенство нулю, возвратит ошибку и прервет процесс

28

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

$ZTrap=”ErrProcCode”. С помощью системной переменной $ZT можно указать строку(ErrProcCode), на которую в случае возникновения ошибки переходит и управление и обработка.

$ETrap=”COSStatement”. В случае возникновения ошибки выполняется выражение COS (COSStatement), указанное как значение системной переменной $ETrap.

Код последней ошибки хранится в системной переменной $ECode в виде ANSI Х11.1 стандарта описания ошибки и в системной переменной $ZError, содержащей наименование ошибки и ее месторасположение.

Пример: 1. $ZTrap.

Abc(I)

S $ZT=”ErrHandl” W 1/I

Q ErrHandl

W !,”$EC = ”_$EC

W !,”$ZE = ”_$ZE

В Caché Terminal:

USER>d ^T1(0)

$EC = ,M6,M9,

$ZE = <DIVIDE>Abc+2^T1

2. $ETrap.

Abc(I)

S $ET="w !,""$EC=""_$EC,!,""$ZE=""_$ZE s $EC="""" " W 1/I

Q

В Caché Terminal:

USER>d ^T1(0) $EC=,M9, $ZE=<DIVIDE>Abc+2^T1

Обратите внимание, что при использовании $ET необходимо обнулять значение системной переменной $EC.

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

XML экспорт/импорт.

В Caché 5. включена поддержка импорта данных из XML документов в объекты Caché и экспорта данных из объектов Caché в XML документы. Кроме этого, разработчику предоставляется COS-интерфейс к SAX парсеру Apache Xerces 1.4., для решения специфических задач манипулирования данными из XML документов.

Универсальность представления данных в Caché, а конкретнее возможность представления данных в виде объектов, позволяет экспортировать объекты Caché в XML документы с минимумом затрат. Рассмотрим возможности Caché по экспорту данных в XML документы.

Экспорт данных.

29

Объектная модель Caché позволяет создавать XML документы напрямую либо из программ Caché:

write "<book isdn="" ",book.isdn, " "" >" write "<title>",book.title, "</title>"

либо из CSP страниц:

<book isdn=" #’book.isdn’# "> <title> #(book.title)# </title>

Рассмотрим экспорт данных на примере создания динамического XML документа, выводящего данные из БД Family. Листинг CSP приложения приведен ниже:

<script language="Cache" runat="Server">

do %response.SetHeader("content-type","txt/xml") write "<?xml version=""1.0""?>"

write "<xml>"

set o=##Class(Family.Family).%OpenId(1) write "<Family>"

write "<Father>"

write "<FIO>",o.Father.FIO,"</FIO>" write "</Father>"

write "<Children>"

write "<FIO>",o.Children.GetAt(1).Personal.FIO,"</FIO>" write "</Children>"

write "</Family>" write "</xml>" do o.%Close()

</script>

Методом SetHeader системного класса %Response выставлен HTTP заголовок, который указывает браузеру, что данный документ является XML документом.

Для экспорта всех свойств класса необходимо либо вывести их с помощью команды write, как показано выше, либо использовать метод XMLExport класса

%XML.Adaptor.

Для использования методов класса %XML.Adaptor, необходимо прописать его как супер-класс или класс-предок для всех классов, которые подлежат экспорту:

Class Family.Family Extends (%Library.Persistent,%XML.Adaptor)

Далее, необходимо создать следующую CSP страницу:

<script language="Cache" runat="Server">

d %response.SetHeader("content-type","txt/xml") w "<?xml version=""1.0""?>"

s o=##Class(Family.Family).%OpenId(1) d o.XMLExport()

d o.%Close() </script>

Также в Caché поддерживается стандарт MS XML-SQL Server, реализованный функциональностью класса %CSP.XMLSQL. За дополнительной информацией обращайтесь к документации класса.

Импорт данных.

Существует два способа импорта данных из документа XML в объекты

БД:

1.Импорт данных непосредственно в классы Caché. В этом случае структура XML документа должна соответствовать структуре

30

Соседние файлы в папке Инфа