Caché Objects QuickStart - InterSystems · языков высокого уровня (Delphi, C#,...

65
Caché Objects QuickStart

Transcript of Caché Objects QuickStart - InterSystems · языков высокого уровня (Delphi, C#,...

 

 

 

 

 

 

 

 

 

 

 

 

Caché Objects QuickStart

C a c h é   O b j e c t s   Q u i c k S t a r t |  2      

Оглавление

Оглавление .................................................................................................................................. 2

Создание классов и работа с объектами .................................................................................. 3

Создание простых свойств и их заполнение ............................................................................. 6

Создание методов и их вызов .................................................................................................. 10

Наследование ............................................................................................................................ 16

Автоматическое создание объектов с тестовыми значениями ............................................. 20

Экспорт данных в XML-файл .................................................................................................... 21

Связанные классы и работа с ними ......................................................................................... 23

Коллекции и их заполнение ...................................................................................................... 26

Отношения и их использование ............................................................................................... 30

Создание и работа с запросами ............................................................................................... 35

Caché Managed Provider для доступа из .NET приложений ................................................... 40

Использование Caché Java Binding для работы с объектами ............................................... 46

Сервер Caché Object для ActiveX в Delphi ............................................................................... 53

Приложение 1. Диаграмма классов ......................................................................................... 59

Приложение 2. Утилиты Caché ................................................................................................. 60

Приложение 3. Подключение к серверу Caché ....................................................................... 63

Приложение 4. Дополнительные источники информации по работе с объектами .............. 65

   

C a c h é   O b j e c t s   Q u i c k S t a r t |  3    

Создание классов и работа с объектами

В данном документе рассматривается создание классов (см. прил. 1) и объектов с

помощью утилит, предоставляемых СУБД Caché (см. прил. 2), и работу с объектами из

языков высокого уровня (Delphi, C#, Java).

Для создания и редактирования классов в Caché предназначена утилита Caché Studio

(Студия). Откройте Студию, подключитесь к пространству имен USER (см. прил. 3),

создайте новый проект (File → New Project) и сохраните его под именем LibraryTest (File → Save Project). Проект объединяет в себе классы, программы на Caché Object Script,

Caché Basic и Caché Server Pages.

Запустите мастер для создания нового класса Human (File → New → General → Cache Class Definition). На первом шаге назовите пакет Test (если поставить имя пакета

User, то при использовании SQL доступа будет конфликт с именем пространства).

На втором шаге выберите тип класса Persistent – хранимый. Это означает, что

экземпляры данного класса будут храниться в БД.

C a c h é   O b j e c t s   Q u i c k S t a r t |  4    

В результате работы мастера получим класс Human.

Сохраните все изменения (File → Save All) и скомпилируйте созданный вами класс

(Build → Compile) иначе он не будет добавлен в библиотеку классов.

C a c h é   O b j e c t s   Q u i c k S t a r t |  5    

Для работы с объектами войдите в Caché Terminal (Терминал) и проверьте, что у вас

установлен пользователь USER:

USER>  

Если нет, выполните команду:

SAMPLES>ZN  "USER"  

Для создания нового объекта класса Human выполните команду:

USER>set  h  =  ##class(Test.Human).%New()  

где Test – имя пакета,

Human – имя класса,

h – переменная, в которой будет храниться указатель на объект.

Для сохранения объекта в БД выполните команду:

USER>do  h.%Save()  

Для освобождения памяти, занятой объектом, выполните команду:

USER>kill  h  

В результате выполненных вами действий у вас в БД появится объект класса Human

с идентификатором 1. Для открытия этого объекта используется команда:

USER>set  h  =  ##class(Test.Human).%OpenId(1)  

Для удаления объекта из БД выполните команду:

USER>do  ##class(Test.Human).%DeleteId(1)  

Данная операция удаляет объект из БД, но не из памяти. Поэтому необходимо

освободить память вручную:

USER>kill  h  

 

C a c h é   O b j e c t s   Q u i c k S t a r t |  6    

Создание простых свойств и их заполнение

Создадим в классе Human свойства Name (типа %String), DateOfBirth (типа %Date) и

Age (типа %Integer).

Для этого воспользуемся мастером создания свойств (Class → Add → Property).

Свойство Name будем заполнять вручную. На первом шаге мастера заполним имя

свойства.

На втором шаге выбираем тип свойства %String и нажимаем Finish.

C a c h é   O b j e c t s   Q u i c k S t a r t |  7    

Аналогично создайте свойство DateOfBirth.

Свойство Age будет рассчитываться автоматически на основании свойства

DateOfBirth. Для его создания первые два шага мастера выполняются аналогично. На

третьем шаге ставим галочку на характеристике поля Calculated.

Пропускаем четвертый шаг и на пятом ставим галочку на опции переопределения

метода Get.

C a c h é   O b j e c t s   Q u i c k S t a r t |  8    

Теперь класс Human в редакторе имеет следующий вид:

/// описание базового класса Человек

Class Test.Human Extends %Persistent

{

/// Имя и фамилия человека

Property Name As %String;

/// Дата рождения человека

Property DateOfBirth As %Date;

/// Возраст человека

Property Age As %Integer [ Calculated ];

Method AgeGet() As %Integer [ ServerOnly = 1 ]

{

Quit ""

}

}

После внесения изменений в класс не забудьте его сохранить и перекомпилировать.

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

Для заполнения свойств объекта используется стандартный точечный синтаксис:

USER>set  h.Name  =  "Петр"  

Дата и время в Caché хранятся во внутреннем формате $HOROLOG – строке,

состоящей из двух целых чисел, разделенных запятой. Первое число – дата, второе –

время. Дата считается как число дней, прошедших с 31 декабря 1840 г. Время считается

как число секунд, прошедших с полуночи. Поэтому, при работе с датой, необходимо

использовать специальные функции:

$ZDate(hdate,  dformat)  –  проверяет значение даты и конвертирует его из внутреннего представления (hdate) в указанный формат (dformat).

C a c h é   O b j e c t s   Q u i c k S t a r t |  9    

$ZDateH(date,  dformat)  –  проверяет значение строки и конвертирует его из строки указанного формата (dformat) во внутреннее представление (date).

Некоторые значения, которые может принимать dformat:

1 MM/DD/[YY]YY, например 07/01/97

3 [YY]YY-MM-DD, например 1997-07-01

4 DD/MM/[YY]YY, например 01/07/97

8 [YY]YYMMDD, например 19970701

Таким образом, дата рождения человека задается с помощью функции:

USER>set  h.DateOfBirth  =  $zdateh("01/01/85",  1)  

Перед заполнением свойств не забудьте создать новый объект, а после заполнения –

сохранить его в БД. Аналогично создайте еще два объекта класса Human, например

Павел с датой рождения 10.02.1956 и Евгений с датой рождения 23.06.1983.

Для вывода на экран значения свойств объекта откройте его и выполните команду:

USER>write  h.Name  

Петр  

USER>write  h.Age  

 

USER>  _  

Свойство Age возвращает пустую строку, поскольку мы его еще не определили.

 

 

C a c h é   O b j e c t s   Q u i c k S t a r t |  10    

Создание методов и их вызов

Добавим к классу Human метод Report, не имеющий аргументов и не возвращающий

никакого значения. Он будет выводить информацию о человеке. Для этого воспользуемся

мастером создания методов (Class → Add → Method).

На первом шаге укажем название метода.

Второй и третий шаг мастера пропускаем без изменений. На четвертом шаге можно

ввести тело метода в окне или заполнить его в теле класса:

write "---", !

write ""_..Name, !

write ""_..Age, !

write "---", !

Получим описание класса:

C a c h é   O b j e c t s   Q u i c k S t a r t |  11    

Обратите внимание, что каждой строке предшествует как минимум 1 пробел. Для

доступа к значениям свойств объекта используется синтаксис ..PropertyName.

Перекомпилируйте класс.

Для вызова созданного метода Report выполните команду do, предварительно

открыв объект:

USER>set  h  =  ##class(Test.Human).%OpenId(2)  

USER>do  h.Report()  

-­‐-­‐-­‐  

Имя:  Петр  

Возраст:    

-­‐-­‐-­‐  

C a c h é   O b j e c t s   Q u i c k S t a r t |  12    

Аналогично создадим метод CalcAge в классе Human, который принимает на вход

дату рождения человека и возвращает возраст. На первом шаге метода указываем имя и

описание.

На втором шаге выбираем тип возвращаемого значения:

И в этом же окне добавляем входящие параметры:

C a c h é   O b j e c t s   Q u i c k S t a r t |  13    

На третьем шаге мастера указываем, что мы создаем метод класса:

Текст метода:

ClassMethod CalcAge(DOB As %Date) As %Integer

{

Quit $ZDate($Horolog,8)-$ZDate(DOB,8)\10000

}

Сделаем метод AgeGet методом-выражением с помощью Инспектора:

C a c h é   O b j e c t s   Q u i c k S t a r t |  14    

Заполним тело метода и перекомпилируем класс:

C a c h é   O b j e c t s   Q u i c k S t a r t |  15    

Обратите внимание, что при обращении к методу класса используется синтаксис,

отличный от обращения к методу объекта: пишется полное имя класса и через точку имя

вызываемого метода.

Теперь, после открытия объекта в Терминале и запроса значения свойства Age получим результат:

USER>set  h  =  ##class(Test.Human).%OpenId(2)  

 USER>w  h.Name  

Петр  

USER>w  h.Age  

27  

Для того чтобы поле Age отображалось при SQL запросах, необходимо в Инспекторе

выставить свойство SqlComputed в true и заполнить свойство SqlComputeCode:

Обратите внимание, что при обращении к значениям свойства объекта из SQL

используются фигурные скобки.

 

C a c h é   O b j e c t s   Q u i c k S t a r t |  16    

Наследование

Создадим новый класс Reader, унаследованный от Human. Для этого на втором шаге

мастера выберите опцию Extends и укажите имя родительского класса.

Таким образом, получим класс Reader, который унаследовал все поля и методы

класса Human.

Добавьте в полученный класс новое свойство ReaderNumber типа %Integer и

переопределите метод Report для вывода на экран значения этого свойства.

В результате получим следующий класс:

/// описание класса Читатель, который наследуется от Человека

Class Test.Reader Extends Test.Human

{

/// номер читательского билета

Property ReaderNumber As %Integer;

C a c h é   O b j e c t s   Q u i c k S t a r t |  17    /// вывод данных о читателе на экран

Method Report()

{

write "---", !

write "Имя: "_..Name, !

write "Возраст: "_..Age, !

write "Номер читательского билета: "_..ReaderNumber, !

write "---", !

}

}

Создадим объект данного класса, заполним его свойства и сохраним в БД:

USER>set  r  =  ##class(Test.Reader).%New()  

 USER>set  r.Name  =  "Павел"  

 USER>set  r.DateOfBirth  =  $zdateh("05/20/81",  1)  

 USER>set  r.ReaderNumber  =  25  

USER>do  r.Report()  

-­‐-­‐-­‐  

Имя:  Павел  

Возраст:  31  

Номер  читательского  билета:  25  

-­‐-­‐-­‐  

USER>do  r.%Save()  

USER>kill  r  

Аналогично создайте класс Librarian, который наследуется от класса Human.

Создайте экземпляр данного класса, заполните его свойства и сохраните его в БД.

C a c h é   O b j e c t s   Q u i c k S t a r t |  18    

В Просмотре Данных Глобалов в Management Portal (Портал управления системой)

Домашняя страница → System Explorer → Глобалы → Запустить → USER → TestHumanD → Просмотр можно увидеть данные объектов классов Human, Reader и

Librarian и хранятся они в одном глобале. Кроме того, обратите внимание, что объекты

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

Чтобы увидеть SQL представление данных необходимо зайти в Management Portal

(Портал управления системой) Домашняя страница → System Explorer → SQL → Просмотр SQL схем → USER:

Выбрать схему Test и в ней нажать на ссылку Open Table в необходимой строке:

Обратите внимание, что в таблице Human есть кроме объектов этого класса также и

объекты классов-наследников:

C a c h é   O b j e c t s   Q u i c k S t a r t |  19    

Также, можно выполнить SQL запрос в Management Portal (Портал управления

системой) Домашняя страница → System Explorer → SQL → Выполнить SQL выражение → USER:

Поскольку класс Reader унаследован от класса Human, то любой объект класса

Reader является и объектом класса Human. Поэтому можно открыть объект с ID = 5 как

объект класса Human:

USER>set  r  =  ##class(Test.Human).%OpenId(5)  

 USER>do  r.Report()  

-­‐-­‐-­‐  

Имя:  Павел  

Возраст:  31  

Номер  читательского  билета:  25  

-­‐-­‐-­‐  

C a c h é   O b j e c t s   Q u i c k S t a r t |  20    

Автоматическое создание объектов с тестовыми значениями

Caché поддерживает множественное наследование. Это, например, позволяет

использовать утилиту, которая автоматически создает и сохраняет указанное количество

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

воспользоваться данной утилитой, необходимо унаследовать класс от системного класса

%Populate.

Отредактируем класс Reader, добавив в список наследования класс %Populate:

Class Test.Reader Extends (Test.Human, %Populate)

Откомпилируйте класс.

Для создания 10 новых объектов в Терминале выполните:

USER>do  ##class(Test.Reader).Populate()  

Чтобы создать другое количество объектов, укажите необходимое число в скобках:

USER>set  cnt  =  ##class(Test.Reader).Populate(15)  

USER>write  cnt  

15  

Метод Populate возвращает число фактически созданных объектов. Кроме того, он

автоматически заполняет не только литеральные свойства, но и ссылочные, в том

случае, если объекты необходимого класса существуют.

C a c h é   O b j e c t s   Q u i c k S t a r t |  21    

Экспорт данных в XML-файл

Отредактируем класс Human: в окне Inspector в свойстве класса Super добавим

родительский класс %XML.Adaptor.

Создадим метод класса для экспорта данных в XML-файл.

Текст метода:

/// экспорт данных в XML-файл

ClassMethod Export(FileName As %String) As %Status

{

open FileName:"WNS"

use FileName

write "<?xml version='1.0' encoding='windows-1251'?>", !

write "<!DOCTYPE Humans [", !

do ##class(Test.Human).XMLDTD()

write "]>", !

write "<Humans>", !

set rs = ##class(%ResultSet).%New("Test.Human:Extent")

set rc = rs.Execute()

while rs.Next() {

C a c h é   O b j e c t s   Q u i c k S t a r t |  22     set id = rs.GetData(1)

set human = ##class(Test.Human).%OpenId(id)

do human.XMLExport()

write !

}

write "</Humans>", !

close FileName

quit $$$OK

}

Запустим метод в Терминале:

USER>do  ##class(Test.Human).Export("c:\humans.xml")  

В результате выполнения метода на диске С: появится файл humans.xml, в котором

будут содержаться данные объектов класса Human и его наследников.

   

C a c h é   O b j e c t s   Q u i c k S t a r t |  23    

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

Создайте хранимый класс ContactInfo в котором будут свойства City, Street и House.

Свойства можно добавлять с помощью соответствующего мастера или вручную. Для

свойства Street укажите максимальную длину 100 символов. Для этого на 4 шаге

мастера в параметре MAXLEN укажите соответствующее число.

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

C a c h é   O b j e c t s   Q u i c k S t a r t |  24    

В классе Human добавьте свойство Contacts типа ContactInfo. В результате мы

получим атрибут Contacts, в котором будет храниться ссылка на объект класса

ContactInfo.

Скомпилируйте класс Human.

В Терминале создайте объекты классов Human и ContactInfo и заполните их

свойства.

USER>set  h  =  ##class(Test.Human).%New()  

 USER>set  h.Name  =  "Анна"  

 USER>set  h.DateOfBirth  =  $zdateh("06/10/95",  1)  

   

USER>set  c  =  ##class(Test.ContactInfo).%New()  

 USER>set  c.City  =  "Москва"  

 USER>set  c.Street  =  "ул.  Дурова"  

 USER>set  c.House  =  "12/1"  

C a c h é   O b j e c t s   Q u i c k S t a r t |  25    

   

Присвойте свойству Contacts ссылку на объект с:

USER>set  h.Contacts  =  c  

Теперь все свойства объекта с доступны через ссылку h.Contacts:

 USER>write  h.Contacts.City_",  "_h.Contacts.Street_"  "_h.Contacts.House  

Москва,  ул.  Дурова  12/1  

Сохраните и закройте объект с:

USER>do  c.%Save()  

 USER>kill  c  

Несмотря на то, что объект с больше не находится в памяти, к нему по прежнему

можно обратиться через ссылку h.Contacts:

USER>set  h.Contacts.Street  =  "пр.  Ватутина"  

 USER>write  h.Contacts.City_",  "_h.Contacts.Street_"  "_h.Contacts.House  

Москва,  пр.  Ватутина  12/1  

Технология, позволяющая по ссылке обращаться к свойствам и методам объекта, не

выполняя дополнительные операции по его открытию и закрытию, называется Свиззлинг

(Swizzling).

Сохраните и закройте объект h.

USER>do  h.%Save()  

 USER>kill  h  

 

C a c h é   O b j e c t s   Q u i c k S t a r t |  26    

Коллекции и их заполнение

В Caché существует два вида коллекций – коллекции-списки и коллекции-массивы.

Коллекции-списки представляют собой упорядоченный список элементов, каждый из

которых определяется своей позицией (целым числом). Коллекция-массив – список пар

(ключ-значение), которые сортируются с помощью ключа. Коллекции могут содержать

константы и ссылки на объекты.

В классе ContactInfo создадим свойство Phones, которое будет коллекцией-

массивом.

Ключом данного массива будет вид номера (мобильный, домашний, рабочий), а

значением – сам номер телефона.

Перекомпилируйте класс.

В Терминале откройте существующий объект класса ContactInfo и добавьте

несколько номеров телефонов:

USER>set  c  =  ##class(Test.ContactInfo).%OpenId(1)  

USER>do  c.Phones.SetAt("+79652246985",  "мобильный")  

USER>do  c.Phones.SetAt("+72545246134",  "домашний")  

Количество элементов в списке:

C a c h é   O b j e c t s   Q u i c k S t a r t |  27    

USER>w  c.Phones.Count()  

2  

Получение значения конкретного элемента:

USER>w  c.Phones.GetAt("домашний")  

+72545246134  

Изменение значения элемента происходит аналогично тому, как оно заполняется:

USER>do  c.Phones.SetAt("+72545246124",  "домашний")  

Удаление элемента из массива:

USER>do  c.Phones.RemoveAt("домашний")  

Сохраните и закройте объект с.

Создайте хранимый класс Book, в котором будут строковые свойства Name, Author и

ISBN.

В классе Reader создайте свойство Books, которое будет коллекцией-списком,

элементами которого будут объекты класса Book.

В Терминале создайте несколько объектов класса Book и сохраните их в БД.

C a c h é   O b j e c t s   Q u i c k S t a r t |  28    

 USER>set  b1  =  ##class(Test.Book).%New()  

 USER>set  b1.Name  =  "Database  Development  For  Dummies"  

 USER>set  b1.Author  =  "Allen  Taylor"  

 USER>set  b1.ISBN  =  "0764507524"  

 USER>do  b1.%Save()  

USER>set  b2  =  ##class(Test.Book).%New()    

USER>set  b2.Name  =  "NoSQL  Distilled  "  

 USER>set  b2.Author  =  "Martin  Fowler"    

USER>set  b2.ISBN  =  "0321826620"    

USER>do  b2.%Save()  

Откройте существующий объект класса Reader:

USER>set  r  =  ##class(Test.Reader).%OpenId(5)  

Вставка элементов в конец списка:

USER>do  r.Books.Insert(b1)  

Вставка элементов в конкретное место списка:

USER>do  r.Books.InsertAt(b2,  2)  

Количество элементов:

USER>w  r.Books.Count()  

2  

Получение значения конкретного элемента:

USER>w  r.Books.GetAt(1).Name  

C a c h é   O b j e c t s   Q u i c k S t a r t |  29    

Database  Development  For  Dummies  

Поскольку у нас элементом списка является объект, то необходимо выводить

значения его свойств.

Удаление элемента из массива:

USER>w  r.Books.RemoveAt(2)  

Изменение значения элемента:

USER>w  r.Books.SetAt(b2,1)  

Сохраните и закройте объект r.

 

C a c h é   O b j e c t s   Q u i c k S t a r t |  30    

Отношения и их использование

В Caché существует два вида отношений (двунаправленных связей между хранимыми

объектами): один ко многим (one-many) и родительский дочерний (parent-children). Parent-

children – зависимая связь и при удалении главного объекта удаляются все дочерние.

Кроме того, невозможно сохранить объект, в котором есть свойство parent, если оно не

заполнено. One-many – независимая связь, т.е. при попытке удаления главного объекта

при существующих дочерних выводится ошибка.

В свойствах, которые обозначены many и children, будут храниться ссылки на

несколько объектов, у которых прописано свойство one и parent.

Создайте хранимый класс Chapter, в котором будут свойства Name (типа %String) и

Page (типа %Integer).

В классе Book создайте свойство Chapters, в котором будет храниться информация

об отношении. На втором шаге мастера укажите тип свойства Relationship.

C a c h é   O b j e c t s   Q u i c k S t a r t |  31    

На третьем шаге мастера выберите тип свойства Children, поскольку у книги может

быть много глав и главы не могут существовать отдельно от книги. Выберите имя класса,

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

Система предложит создать свойство в классе Chapter, поскольку его там еще нет.

C a c h é   O b j e c t s   Q u i c k S t a r t |  32    

Теперь в классе Chapter есть свойство bookid, а в классе Book есть свойство

Chapters:

Relationship Chapters As Test.Chapter [ Cardinality = children, Inverse = bookid ];

Relationship bookid As Test.Book [ Cardinality = parent, Inverse = Chapters ];

Перекомпилируйте классы.

Создайте несколько глав и откройте существующую книгу.

USER>set  c1  =  ##class(Test.Chapter).%New()  

 USER>set  c1.Name  =  "Introduction"  

 USER>set  c1.Page  =  10  

   

USER>set  c2  =  ##class(Test.Chapter).%New()  

 USER>set  c2.Name  =  "Development  of  DB"  

 USER>set  c2.Page  =  13  

 

USER>set  b  =  ##class(Test.Book).%OpenId(1)  

Свяжите книгу с главами двумя способами:

USER>do  b.Chapters.Insert(c1)  

USER>set  c2.bookid  =  b  

Теперь можно получить информацию об объектах с обеих сторон отношения:

USER>w  b.Chapters.GetAt(1).Name  

Introduction  

USER>w  c2.bookid.Name  

Database  Development  For  Dummies  

C a c h é   O b j e c t s   Q u i c k S t a r t |  33    

Как видите, со стороны Children (Book) работа с отношением аналогична работе с

коллекцией-списком, а со стороны One (Chapter) – со ссылкой.

Сохраните объект Book и посмотрите на глобалы, соответствующие обоим классам:

Портал управления системой → System Explorer → Глобалы → Запустить → USER → Test.ChapterD → Просмотр и Портал управления системой → System Explorer → Глобалы → Запустить → USER → Test.BookD → Просмотр.

Закройте все объекты и удалите книгу, в которую вы только что добавляли главы. У

вас удалилась книга и все ее главы.

Создайте хранимый класс Library, в котором есть свойство Name типа %String и

Contacts типа ContactInfo. Свойство Books будет отношением один ко многим с классом

Book. Первые два шага мастера выполняются аналогично отношению родительский

дочерний, а на третьем шаге выбираем тип отношения Many (поскольку в одной

библиотеке может быть много книг, но книги существуют и не только в библиотеке), класс

и имя свойства.

На следующем шаге система предложит создать свойство и индекс для него.

В результате получим свойство Books в классе Library, свойство idlibrary в классе

Book и индекс idlibraryIndex в классе Book:

Relationship Books As Test.Book [ Cardinality = many, Inverse = idlibrary ];

C a c h é   O b j e c t s   Q u i c k S t a r t |  34    

Relationship idlibrary As Test.Library [ Cardinality = one, Inverse = Books ];

Index idlibraryIndex On idlibrary;

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

Создайте объект класса Library и добавьте в него книги. Работа с отношением один

ко многим осуществляется аналогично работе с отношением родительский дочерний.

Однако если вы захотите удалить библиотеку и к ней приписана хотя бы одна книга,

то система вам вернет ошибку:

USER>set  sc  =  ##class(Test.Library).%DeleteId(1)  

USER>do  $system.OBJ.DisplayError(sc)  

 ОШИБКА  #5823:  Не  удается  удалить  объект,  на  который  ссылается  'Test.Book.idlibrary'  

Таким образом, в отношении один ко многим необходимо «отвязать» все зависимые

объекты перед удалением.

В классе Library создайте свойство Librarians, которое будет отношением с классом

Librarian. Учтите, что библиотекарь может существовать вне библиотеки. Создайте

несколько объектов класса Librarian и заполните все их свойства.

 

C a c h é   O b j e c t s   Q u i c k S t a r t |  35    

Создание и работа с запросами

Создадим в классе Human запрос ByName, который будет возвращать список людей,

у которых имя начинается с указанной буквы. Запрос принимает один параметр

FirstLetter типа %String, и возвращает значения полей Name, Age и контактную

информацию, при условии, что имя человека начинается с указанной буквы.

Возвращаемые данные сортируются по дате рождения.

Для создания запроса открываем мастер Class → Add → Query. На первом шаге

вводим имя запроса и выбираем тип запроса This Query is based on an SQL statement.

На следующем шаге создаем входящий параметр FirstLetter типа %String.

C a c h é   O b j e c t s   Q u i c k S t a r t |  36    

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

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

C a c h é   O b j e c t s   Q u i c k S t a r t |  37    

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

объявить как процедуру. Для этого в Инспекторе в свойстве SqlProc выберите true.

В результате ваш запрос должен выглядеть:

/// возвращает список людей, у которых имя начинается с указанной буквы

Query ByName(FirstLetter As %String) As %SQLQuery [ SqlProc ]

{

SELECT Name,

Age,

Contacts->City,

Contacts->Street,

Contacts->House

C a c h é   O b j e c t s   Q u i c k S t a r t |  38     FROM Human

WHERE (Name %STARTSWITH :FirstLetter)

ORDER BY DateOfBirth

}

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

Для работы с запросами используется класс %ResultSet. В Терминале сначала

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

выполняться.

USER>set  rs  =  ##class(%ResultSet).%New("Test.Human.ByName")  

Далее выполняем запрос и передаем значение параметра:

USER>do  rs.Execute("П")  

Выводим результат на экран:

USER>do  rs.%Display()  

Name        Age          City        Street    House  

Павел  56  Москва  "пер.  Олений"  25  

Павел  31  Москва  "пер.  Олений"  1A  

Петр  27  Москва  "ул.  Воздушная"  21  

 3  Rows(s)  Affected  

Освобождаем память:

USER>kill  rs  

С запросами проще работать, если создать программу. Для этого в Студии

выполняем File → New → General → Cache Object Script Routine. В открывшемся окне

пишем текст программы:

QueryHumans(FirstLetter)

new rs

set rs = ##class(%ResultSet).%New()

C a c h é   O b j e c t s   Q u i c k S t a r t |  39     set rs.ClassName = "Test.Human"

set rs.QueryName = "ByName"

set sc = rs.Execute(FirstLetter)

if sc = 1 {

while rs.Next() {

write $JUSTIFY(rs.Get("Name"),10)_

$JUSTIFY(rs.Get("Age"),15)_

$JUSTIFY(rs.Get("City"),10)_

$JUSTIFY(rs.Get("Street"),15)_

$JUSTIFY(rs.Get("House"),5), !

}

}

kill rs

quit

Обратите внимание на наличие как минимум одного пробела перед командами во

всех строках, кроме первой. В ней находится имя процедуры и параметр.

Сохраните программу в проекте LibraryTest под именем QueryHumans.mac (File → Save) и откомпилируйте ее.

Вызовите сохраненную программу в Терминале:

USER>do  ^QueryHumans("П")  

       Павел                            56      Москва      пер.  Олений    25  

         Павел                          31      Москва      пер.  Олений    1А  

           Петр                          27      Москва  ул.  Воздушная    21  

При необходимости заполните недостающие поля.

C a c h é   O b j e c t s   Q u i c k S t a r t |  40    

Caché Managed Provider для доступа из .NET приложений

Caché Managed Provider предоставляет доступ к данным, хранящимся в БД Caché, из

.NET приложений. Использует API без использования объектно-реляционного мапинга и

характеризуется тем, что:

-­‐ предоставляет неограниченный реляционный доступ, используя ADO.NET API;

-­‐ предоставляет объектный доступ к данным, используя прокси-классы;

-­‐ написан на .NET;

-­‐ является thread-safe, т.е. может использоваться в многопоточных приложениях.

Caché Managed Provider состоит из:

� Caché Object Server – сервер, который управляет связью между .NET приложением

и БД Caché, используя стандартный протокол TCP/IP;

� Intersystems.Data.CacheClient – набор .NET классов, в которых прописан

функционал .NET классов, создаваемых Caché Proxy Generator’ом;

� Caché Proxy Generator – набор методов, которые генерируют .NET классы из Caché

классов.

Создайте новый проект из шаблона Windows Forms Application. Добавьте в него

ссылку на InterSystems.Data.CacheClient.dll (Project → Add reference → Browse → “C:\Intersystems\Cache\Dev\dotnet\Bin” → InterSystems.Data.CacheClient.dll). В файл

формы добавьте using InterSystems.Data.CacheClient;

Для соединения с БД используется объект класса CacheConnection, который

содержит:

1) свойство string ConnectionString – содержит строку подключения к БД;

2) метод void Open() – отвечает за соединение с БД;

3) метод string ConnectDlg() – отображает диалоговое окно для задания параметров

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

4) метод void Close() – закрывает соединение с сервером БД.

C a c h é   O b j e c t s   Q u i c k S t a r t |  41    

Вынесите на форму две кнопки. Первая будет отвечать за подключение в БД, а

вторая – за его разрыв. В обработчике события Click первой кнопки напишите код:

private void button1_Click(object sender, EventArgs e) { try { CacheConnect = new CacheConnection(); CacheConnect.ConnectionString = CacheConnection.ConnectDlg(); CacheConnect.Open(); } catch (Exception eConn){ MessageBox.Show("CreateConnection error: " + eConn.Message); }

}

В обработчике события Click второй кнопки напишите код:

private void button2_Click(object sender, EventArgs e) { try { CacheConnect.Close(); } catch (Exception eConn) { MessageBox.Show("CloseConnection error: " + eConn.Message); }

}

Добавьте свойство в класс:

private CacheConnection CacheConnect;

Сохраните и запустите программу.

Для получения объектного доступа к БД необходимо сначала сформировать прокси-

классы для Caché классов. Для этого откройте Caché Proxy Generator

(C:\Intersystems\Cache\Dev\dotnet\Bin\CacheNetWizard.exe). В открывшемся окне

выберите подключение к серверу (см. прил. 3), опцию Source Files, путь к папке вашего

проекта, классы для генерации и нажмите кнопку Generate.

C a c h é   O b j e c t s   Q u i c k S t a r t |  42    

По указанному пути у вас должен появиться созданный генератором файл. Добавьте

его в проект (Project → Add existing item).

В файл формы добавьте:

using InterSystems.Data.CacheTypes;

using Test;

Кроме свойств и методов, определенных пользователем, в сгенерированных классах

присутствуют методы, реализующие чтение, запись, удаление и закрытие объекта:

1) метод OpenId(InterSystems.Data.CacheClient.CacheConnection conn, string id, out InterSystems.Data.CacheTypes.CacheStatus status) – возвращает ссылку на

объект соответствующего класса;

C a c h é   O b j e c t s   Q u i c k S t a r t |  43    

2) метод Save() – сохраняет объект в БД и возвращает статус;

3) метод Close() – закрывает объект и доступ к нему в БД.

Создание объекта выполняется с помощью стандартного синтаксиса C#. В

конструктор объекта передается ссылка на подключение к БД.

Вынесите на форму текстовое поле и кнопку. В текстовое поле будет вводиться

идентификатор объекта для открытия, а по кнопке существующий объект будет

открываться. В обработчике события Click кнопки напишите код:

private void button3_Click(object sender, EventArgs e) { CacheStatus status; Human human = Human.OpenId(CacheConnect, textBox1.Text, out status); if (!status.IsOK) { MessageBox.Show(status.Message); } else { MessageBox.Show("Имя: " + human.Name + "\n" + "Возраст: " + human.Age.ToString() + "\n" + "Дата рождения: " + human.DateOfBirth.ToString() + "\n" + "Адрес: " + human.Contacts.City + ", " + human.Contacts.Street + " " + human.Contacts.House); human.Close(); human.Dispose();

}

}

Обратите внимание, что к свойствам объекта класса ContactInfo, на который

хранится ссылка в объекте класса Human, доступ осуществляется с помощью

стандартного точечного синтаксиса.

Сохраните и запустите программу. Введите идентификатор существующего объекта

класса Human в котором есть ссылка на существующий объект класса ContactInfo

(например, 2) и проверьте правильность вывода данных.

Вынесите на форму текстовое поле, поле выбора даты и кнопку. В текстовое поле

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

обработчике события Click кнопки напишите код:

private void button4_Click(object sender, EventArgs e) {

C a c h é   O b j e c t s   Q u i c k S t a r t |  44     CacheStatus status; Human human = new Human(CacheConnect); human.Name = textBox2.Text; human.DateOfBirth = dateTimePicker1.Value; status = human.Save(); if (!status.IsOK) { MessageBox.Show(status.Message); } human.Close(); human.Dispose();

}

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

Вынесите на форму кнопку, которая будет вызывать метод Export класса Human. В

обработчике события Click кнопки напишите код:

private void button5_Click(object sender, EventArgs e) { CacheStatus status; status = Human.Export(CacheConnect, "C:\test.xml"); if (!status.IsOK) { MessageBox.Show(status.Message); }

}

Сохраните и запустите программу. Проверьте создается ли файл и какие в нем

данные.

Для работы с запросами используются классы, которые наследуются от

соответствующих классов ADO Provider:

-­‐ CacheConnection – отвечает за соединение с сервером БД;

-­‐ CacheCommand – инкапсулирует SQL-выражение или хранимую процедуру;

-­‐ CacheDataReader – предоставляет функционал для однонаправленного получения

данных результата выполнения CacheCommand;

-­‐ CacheDataAdapter – инкапсулирует результат выполнения CacheCommand и

используется для заполнения ADO Dataset’а и обновления данных в БД.

Предоставляет двунаправленный доступ к данным.

C a c h é   O b j e c t s   Q u i c k S t a r t |  45    

Вынесите на форму кнопку и многострочное текстовое поле. В обработчике события

Click кнопки напишите код:

private void button6_Click(object sender, EventArgs e) { CacheCommand command = Human.ByName(CacheConnect); CacheParameter Name_param = new CacheParameter("FirstLetter", CacheDbType.NVarChar); Name_param.Value = "П"; command.Parameters.Add(Name_param); CacheDataReader Reader = command.ExecuteReader(); while (Reader.Read()) { richTextBox1.AppendText(Reader[Reader.GetOrdinal("Name")] + ": " + Reader[Reader.GetOrdinal("Age")] + ": " + Reader[Reader.GetOrdinal("City")] + ": " + Reader[Reader.GetOrdinal("Street")] + ": " + Reader[Reader.GetOrdinal("House")]+"\n"); }; Reader.Close(); command.Dispose();

}

Сохраните и запустите программу. Проверьте правильность полученных данных.

C a c h é   O b j e c t s   Q u i c k S t a r t |  46    

Использование Caché Java Binding для работы с объектами

Caché Java Binding предоставляет доступ к БД из приложений, написанных на Java и

состоит из:

� Caché Java Class Generator – расширение компилятора классов Caché, которое

позволяет генерировать Java классы из существующих Caché классов,

определенных в словаре (Caché Class Dictionary);

� Caché Java Class Package (CacheDB.jar) – пакет, содержащий Java классы, которые

реализуют методы, унаследованные от системных классов Caché;

� Caché Object Server – сервер, который управляет доступом из клиентов к серверу

БД.

Для правильной работы клиента необходимо иметь Java SDK как минимум 1.5 версии.

Для каждой версии существует своя библиотека CacheDB.jar, находящаяся в папке

C:\InterSystems\Cache\dev\java\lib .

Создайте новый проект Java Project. Добавьте в него библиотеки CacheDB.jar и

cachejdbc.jar (Project → Properties → Java build Path → Libraries → Add external JARs → “C:\InterSystems\TryCache\dev\java\lib\JDK16”). Добавьте в проект новый класс, в

котором будет метод public static void main(String[] args). Добавьте в созданный класс

импорты:

import com.intersys.objects.CacheDatabase; import com.intersys.objects.CacheException; import com.intersys.objects.Database;

Для соединения с БД создайте метод Database createConnection():

public static Database createConnection() throws CacheException { String url="jdbc:Cache://localhost:1972/USER"; String username="_SYSTEM"; String pwd="SYS"; Database db = CacheDatabase.getDatabase(url, username, pwd); return db;

}

Вызовите метод из процедуры main:

C a c h é   O b j e c t s   Q u i c k S t a r t |  47     try { db = createConnection();

} catch (CacheException e) {System.out.println(e.getMessage());}

 

Добавьте свойство в объявление класса:

static Database db;

Сохраните и запустите программу.

Для получения объектного доступа к БД необходимо сначала сформировать прокси-

классы (проекции) для Caché классов. Для этого необходимо во все классы в Студии

добавить свойство Projection (Class → Add → New Projection). На первом шаге мастера

задайте имя проекции.

Выберите тип проекции и путь, куда будут выкладываться сгенерированные файлы.

C a c h é   O b j e c t s   Q u i c k S t a r t |  48    

Повторите процедуру для всех классов или просто скопируйте полученную строку:

Projection LibraryProjection As %Projection.Java(ROOTDIR = "C:\ ");

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

сгенерированные файлы. Добавьте их в проект.

Кроме свойств и методов, определенных пользователем, в сгенерированных классах

присутствуют методы, реализующие чтение, запись, удаление и закрытие объекта:

1) метод _open(Database db, Id id) – возвращает ссылку на объект

соответствующего класса;

2) метод _save() – сохраняет объект в БД и возвращает статус.

Создание объекта и заполнение его свойств выполняется с помощью стандартного

синтаксиса Java (POJO). В конструктор объекта передается ссылка на подключение к БД.

Для работы с объектами импортируйте файлы:

import test.Human; import com.intersys.objects.Id;

Для просмотра свойств объекта Human добавьте код в блок try-catch после открытия

соединения с БД:

C a c h é   O b j e c t s   Q u i c k S t a r t |  49    Human human = (Human)(Human._open(db, new Id(2))); System.out.println("Имя: " + human.getName() + "\n" + "Возраст: " + human.getAge().toString() + "\n" + "Дата рождения: " + human.getDateOfBirth().toString() + "\n" +

"Адрес: " + human.getContacts().getCity() + ", " + human.getContacts().getStreet() + " " + human.getContacts().getHouse());

db.closeObject(human.getOref());

Обратите внимание, что к свойствам объекта класса ContactInfo, на который

хранится ссылка в объекте Human, доступ осуществляется с помощью стандартного

точечного синтаксиса.

Сохраните и запустите программу. Введите идентификатор существующего объекта

класса Human в котором есть ссылка на существующий объект класса ContactInfo

(например, 2) и проверьте правильность вывода данных.

Для создания объекта класса Human добавьте код:

Human newHuman = new Human(db); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String humanName = null; String humanAge = null; try { System.out.print("Введите имя человека: "); humanName = br.readLine(); System.out.print("Введите дату рождения человека в формате yyyy-mm-dd: "); humanAge = br.readLine(); } catch (IOException ioe) { System.out.println("IO error trying to read your name!"); System.exit(1); } newHuman.setName(humanName); newHuman.setDateOfBirth(Date.valueOf(humanAge)); if (newHuman.save()!=1){ System.out.println("Problem occured while creating a record");

}

db.closeObject(newHuman.getOref());

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

C a c h é   O b j e c t s   Q u i c k S t a r t |  50    

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

интерфейс. Добавьте код в вашу программу:

Human.Export(db, "C:/exp.xml");

Сохраните и запустите. Проверьте создается ли файл и какие в нем данные.

Caché автоматически генерирует методы для каждого метода-запроса в классе и

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

com.intersys.objects.CacheQuery. Результат выполнения запроса возвращается в объект

стандартного класса java.sql.ResultSet, который может генерировать исключительную

ситуацию SQLException.

Добавьте код в вашу программу:

try {

CacheQuery query = new CacheQuery(db, "Test.Human", "ByName"); java.sql.ResultSet rs=query.execute("П"); while (rs.next()){ for (int j=0;j<rs.getMetaData().getColumnCount() ; j++) { System.out.print(rs.getString(j+1)+" "); } System.out.println();

} catch (SQLException e) {e.printStackTrace();}

rs.close(); query.close();

Сохраните и запустите. Проверьте правильность полученных данных.

В результате у вас должен получиться класс:

package Test.ua; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.sql.Date; import java.sql.SQLException; import Test.Human; import com.intersys.objects.CacheDatabase; import com.intersys.objects.CacheException; import com.intersys.objects.CacheQuery;

C a c h é   O b j e c t s   Q u i c k S t a r t |  51    import com.intersys.objects.Database; import com.intersys.objects.Id; public class main { static Database db; public static void main(String[] args) { try { db = createConnection(); //открытие объекта Human human = (Human)(Human._open(db, new Id(2))); System.out.println("Имя: " + human.getName() + "\n" + "Возраст: " + human.getAge().toString() + "\n" + "Дата рождения: " + human.getDateOfBirth().toString() + "\n" + "Адрес: " + human.getContacts().getCity() + ", " + human.getContacts().getStreet() + " " + human.getContacts().getHouse());

db.closeObject(human.getOref()); //создание нового объекта Human newHuman = new Human(db); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String humanName = null; String humanAge = null; try { System.out.print("Введите имя человека: "); humanName = br.readLine(); System.out.print("Введите дату рождения человека в формате yyyy-mm-dd: "); humanAge = br.readLine(); } catch (IOException ioe) { System.out.println("IO error trying to read your name!"); System.exit(1); } newHuman.setName(humanName); newHuman.setDateOfBirth(Date.valueOf(humanAge)); if (newHuman.save()!=1){ System.out.println("Problem occured while creating a record"); }

db.closeObject(newHuman.getOref()); //выполнение метода класса Human.Export(db, "C:/exp.xml"); //работа с запросами

C a c h é   O b j e c t s   Q u i c k S t a r t |  52     CacheQuery query = new CacheQuery(db, "Test.Human", "ByName"); java.sql.ResultSet rs=query.execute("П"); while (rs.next()){ for (int j=0;j<rs.getMetaData().getColumnCount() ; j++) { System.out.print(rs.getString(j+1)+" "); } System.out.println(); } rs.close(); query.close(); } catch (CacheException e) {System.out.println(e.getMessage());} catch (SQLException e) {e.printStackTrace();} } public static Database createConnection() throws CacheException { String url="jdbc:Cache://localhost:1972/USER"; String username="_SYSTEM"; String pwd="SYS"; Database db = CacheDatabase.getDatabase(url, username, pwd); return db; } }

 

C a c h é   O b j e c t s   Q u i c k S t a r t |  53      

Сервер Caché Object для ActiveX в Delphi

Используя Caché Object Server для ActiveX, можно получить доступ к данным,

хранящимся в БД, из программ, написанных на языках высокого уровня (Delphi, C#, C++,

Basic). Этот сервер регистрируется автоматически при установке сервера БД. Состоит он

из шести интерфейсов:

� IFactory – фабрика объектов Caché, отвечает за доступ к БД и работу с объектами.

� IResultSet – интерфейс для работы с динамическими запросами и запросами

класса.

� IBinaryStream – интерфейс для работы с бинарными потоками.

� ICharStream – интерфейс для работы со строковыми потоками.

� IObjInstance – не имеет реализации, оставлен для обратной совместимости.

Есть несколько подходов к работе с ActiveX. В данном случае будем использовать

позднее связывание.

Создайте проект в Delphi. Добавьте в программе в раздел uses файл ComObj.

Работа с интерфейсом IFactory

В этом интерфейсе реализованы методы работы с БД и объектами, которые можно

условно разделить на 5 групп:

соединение с БД;

работа с объектами;

создание запросов;

управление транзакциями;

обработка исключительных ситуаций.

К первой группе методов относятся:

1) function ConnectDlg(Title: OleVariant): WideString – диалоговое окно для задания

параметров подключения к БД, параметром является заголовок окна и результатом

ее является строка подключения.

C a c h é   O b j e c t s   Q u i c k S t a r t |  54    

2) function Connect(const conn_str: WideString): WordBool – осуществляет

подключение к БД, ее параметром является строка подключения, а результатом –

признак успешности выполнения.

Формат строки подключения: cn_iptcp:ipaddress[port]:namespace, где ipaddress – ip

адрес сервера (localhost) или полное доменное имя, port – номер порта (1972),

namespace – пространство имен (User).

3) function IsConnected: WordBool – проверяет, существует ли соединение с

сервером;

4) function Disconnect: WordBool – разрывает соединение с БД.

На форму вынесите две кнопки. Первая будет отвечать за подключение в БД, а

вторая – за его разрыв. В обработчике события OnClick первой кнопки напишите код:

procedure TForm1.Button1Click(Sender: TObject);

begin

cacheobj := CreateOleObject('CacheActiveX.Factory');

if cacheobj.connect(cacheobj.ConnectDlg())

then

showmessage('Success!')

else

showmessage('Failure!');

end;

В обработчике события OnClick второй кнопки напишите код:

procedure TForm1.Button2Click(Sender: TObject);

begin

if cacheobj.IsConnected then cacheobj.Disconnect;

end;

Вынесите объявление переменной в раздел private класса:

private

cacheobj:variant;

Сохраните и запустите программу.

Ко второй группе методов относятся:

C a c h é   O b j e c t s   Q u i c k S t a r t |  55    

1) function New(const ClassName: WideString; InitVal: OleVariant): IDispatch –

создает объект класса ClassName и возвращает ссылку на интерфейс

диспетчеризации IDispatch;

2) function OpenId(const ClassName: WideString; const ID: WideString; Concurrency: OleVariant): IDispatch – открывает существующий объект класса

ClassName, ID которого равно ID и возвращает ссылку на интерфейс

диспетчеризации IDispatch;

После получения ссылки на интерфейс диспетчеризации, с объектом можно работать,

как с обычным объектом в Delphi, т.е. можно изменять его свойства и вызывать его

методы. Для сохранения объекта в БД необходимо вызывать метод sys_Save, а для

закрытия - sys_Close.

Вынесите на форму текстовое поле и кнопку. В текстовое поле будет вводиться

идентификатор объекта для открытия, а по кнопке существующий объект будет

открываться. В обработчике события OnClick кнопки напишите код:

procedure TForm1.Button3Click(Sender: TObject);

var human:variant;

begin

if cacheobj.IsConnected then

begin

human := cacheObj.OpenId('Test.Human', strtoint(edit1.Text));

showmessage('Имя: '+human.Name+sLineBreak+

'Возраст: '+inttostr(human.Age)+sLineBreak+

'Дата рождения: '+datetostr(human.DateOfBirth)+sLineBreak+

'Адрес: '+human.Contacts.City+', '+human.Contacts.Street+' '+human.Contacts.House);

human.sys_close;

end;

end;

Обратите внимание, что к свойствам объекта класса ContactInfo, на который

хранится ссылка в объекте Human, доступ осуществляется с помощью стандартного

точечного синтаксиса.

Сохраните и запустите программу. Введите идентификатор существующего объекта

класса Human в котором есть ссылка на существующий объект класса ContactInfo

(например, 2) и проверьте правильность вывода данных.

C a c h é   O b j e c t s   Q u i c k S t a r t |  56    

Вынесите на форму текстовое поле, поле выбора даты и кнопку. В текстовое поле

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

обработчике события OnClick кнопки напишите код:

procedure TForm1.Button4Click(Sender: TObject);

var human:variant;

begin

if cacheobj.IsConnected then

begin

human := cacheObj.New('Test.Human');

human.name := Edit2.Text;

human.dateofbirth := DateTimePicker1.Date;

human.sys_Save;

human.sys_Close;

end;

end;

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

Вынесите на форму кнопку, которая будет вызывать метод Export класса Human. В

обработчике события OnClick кнопки напишите код:

procedure TForm1.Button5Click(Sender: TObject);

begin

if cacheobj.IsConnected then

cacheObj.OpenId('Test.Human', strtoint(edit1.Text)).Export('c:\test.xml');

end;

Сохраните и запустите программу. Проверьте создается ли файл и какие в нем

данные.

К третьей группе методов относятся:

1) function DynamicSQL(const Statement: WideString): IDispatch – принимает SQL-

запрос и возвращает ссылку на интерфейс диспетчеризации, с которым можно

работать как с IResultSetDisp;

2) function ResultSet(const ClassName: WideString; const QueryName: WideString): IDispatch – в классе ClassName находит Query с именем QueryName и возвращает

C a c h é   O b j e c t s   Q u i c k S t a r t |  57    

ссылку на интерфейс диспетчеризации, с которым можно работать как с

IResultSetDisp.

Работа с интерфейсом IResultSet

В этом интерфейсе реализованы методы работы с динамическими запросами и

запросами класса. Для того чтобы запросы класса работали, они должны иметь

модификатор SqlProc.

В этом интерфейсе реализованы методы:

1) function Execute(par1: OleVariant; par2: OleVariant; par3: OleVariant; par4: OleVariant; par5: OleVariant; par6: OleVariant; par7: OleVariant; par8: OleVariant; par9: OleVariant; par10: OleVariant; par11: OleVariant; par12: OleVariant; par13: OleVariant; par14: OleVariant; par15: OleVariant; par16: OleVariant): WordBool –

выполняет запрос;

2) function Next: WordBool – переходит к следующей строке результата выполнения

запроса;

3) function Close: WordBool – закрывает доступ к результатам выполнения запроса и

освобождает память;

4) function GetData(idx: Smallint): OleVariant – возвращает значение idx-ной колонки;

5) function GetDataAsString(idx: Smallint): WideString – возвращает значение idx-

ной колонки с преобразованием его в строку;

6) function Get(const col_name: WideString): OleVariant – возвращает значение

колонки с именем col_name.

Вынесите на форму кнопку и многострочное текстовое поле. В обработчике события

OnClick кнопки напишите код:

procedure TForm1.Button6Click(Sender: TObject);

var humans:variant;

begin

Memo1.Lines.Clear;

if cacheobj.IsConnected then

begin

humans := cacheobj.ResultSet('Test.Human', 'ByName');

humans.Execute('П');

C a c h é   O b j e c t s   Q u i c k S t a r t |  58    

while humans.next do

Memo1.Lines.Add(humans.GetData(1)+' '+humans.GetData(2)+' '+humans.GetData(3)+' '+humans.GetData(4)+' '+humans.GetData(5));

humans.close;

end;

end;

 

Сохраните и запустите программу. Проверьте правильность полученных данных.

 

C a c h é   O b j e c t s   Q u i c k S t a r t |  59      

Приложение 1. Диаграмма классов

 

C a c h é   O b j e c t s   Q u i c k S t a r t |  60    

Приложение 2. Утилиты Caché

Для работы с БД Caché существует набор утилит:

� Студия – Caché Studio;

� Терминал – Caché Terminal;

� Портал управления системой – Management Portal.

Эти утилиты могут запускаться из меню пуск:

или из Caché куба, находящегося в трэе :

Студия – интегрированная среда для разработки модели БД, написания программ и

Web-приложений:

дает возможность создавать и редактировать определения классов, CSP-страниц,

программ на языке Caché Object Script (COS) используя единую среду;

поддерживает полнотекстовое редактирование кода с подсветкой команд и

проверкой синтаксиса языков COS, Basic, Java, SQL, JavaScript, HTML, XML;

поддерживает депозитарии кода;

C a c h é   O b j e c t s   Q u i c k S t a r t |  61    

позволяет производить отладку;

организовывает код проекта;

предоставляет мастера для создания классов, методов, свойств, связей, Web-

форм;

поддерживает версионность.

Терминал можно использовать для отладки программ, процедур, функций та

проверки работы отдельных операторов. Работа ведется в режиме командной строки:

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

Главное  меню   Панель  «Стандартная»  

Панель  «Отладка»  

Панель  «Члены»  

Панель  «Закладка»  Рабочая  поверхность  

Область  инспектора  

Область  вывода  

Область  просмотра  значений  

Область  редактирования  

Строка  состояния  

C a c h é   O b j e c t s   Q u i c k S t a r t |  62    

Портал управления системой содержит утилиты, необходимые для конфигурации

системы, просмотра данных и выполнения операций.

   

C a c h é   O b j e c t s   Q u i c k S t a r t |  63    

Приложение 3. Подключение к серверу Caché

При открытии Студии требуется выполнить подключение к серверу. Для подключения

к пространству имен User необходимо:

1. В окне Cache Connection Manager нажать на кнопку Connect

2. В открывшемся окне Server Connection выбрать доступный сервер и нажать OK

C a c h é   O b j e c t s   Q u i c k S t a r t |  64    

3. В окне Log on to <ServerName> ввести логин и пароль. Стандартный пароль для

пользователя _SYSTEM - sys.

4. В окне Cache Connection Manager появится список доступных пространств имен на

выбранном сервере. Из списка выберите USER и нажмите OK

 

C a c h é   O b j e c t s   Q u i c k S t a r t |  65    

Приложение 4. Дополнительные источники информации по работе с объектами

Более подробную информацию по работе с объектами можно найти в документации

Caché (Caché куб → Documentation):

� Using Caché Objects;

� Caché Programming Orientation Guide;

� Projecting Objects to XML;

� Using the Caché Managed Provider for .NET;

� Using Java with Caché;

� Caché with Java QuickStart Tutorial;

� Caché Managed Provider for .NET Tutorial;

� Using ActiveX with Caché.

А также в литературе:

1) Кирстен В., Иренгер И., Рёриг Б., Шульте П. СУБДCaché: объектно-

ориентированная разработка приложений. - СПб, «Питер», 2001.

2) Кречетов Н., Петухова Е., Скворцов В., Умников А., Щукин Б.

Постреляционная технология Caché для реализации объектных приложений. – М.,

МИФИ, 2001.

Дополнительные материалы Вы можете найти в разделе Разработчику сайта

Московского представительства Intersystems Corp. , техническом блоге InterSystems

http://www.writeimagejournal.com и блоге компании на Хабрахабр.

Дополнительную информацию Вы можете получить в российском представительстве

InterSystems Corp.