Офисная надстройка над документооборотом
А. Кузнецов, Е. Плискин, И. Янишевский
март 2003 г.
АННОТАЦИЯ
Решается задача встраивания системы управления документооборотом (СУД) в офисную систему автоматизации работы аппарата руководителя (САР), которая включает планирование рабочего дня руководителя и двойной контроль исполнения документов: на уровне аппарата руководителя и на уровне инспекторов по контролю за исполнением поручений.
На каждом рабочем месте создается локальная база данных (ЛБД). В ней содержатся все версии каждого мероприятия, созданные различными участниками в процессе планирования рабочего дня руководителя. Новая версия мероприятия сначала создается некоторым участником в своей ЛБД, затем сохраняется на сервере в упакованном виде, затем подкачивается с сервера другими участниками и записывается в их ЛБД.
Стыковка с СУД включает «инкрементальную» подкачку документов из СУД в ЛБД, при этом в ЛБД подкачиваются с сервера только новые и измененные версии «нужных» документов. Кроме того, сервер документооборота используется как «общая информационная шина», для перекачки планируемых мероприятий между участниками. Хотя описание мероприятия в ЛБД имеет сложную структуру, но на сервере версии описаний мероприятий хранятся в одной реляционной таблице в сжатом виде. Описывается создание и хранение версий мероприятий в локальной базе данных (ЛБД) и на сервере.
Приводятся практические рецепты программирования доступа к ЛБД на языке Visual Basic.
2 Введение
2.1 Постановка задачи
Решается задача встраивания некоторой системы управления документооборотом (СУД) [1] в офисную систему специального назначения, которая предназначена для эксплуатации в аппарате руководителя (АР) и включает планирование рабочего дня руководителя и контроль исполнения документов. Благодаря стыковке системы аппарата руководителя (САР) с системой управления документооборотом (СУД) достигается двойной контроль исполнения: на уровне референтов руководителя и на уровне инспекторов по контролю за исполнением поручений.
План работы руководителя состоит из мероприятий различных типов: обычные мероприятия, совещания по нескольким вопросам, доклады документов, командировки и другие. Обычное мероприятие характеризуется темой, списком участников, датой и временем проведения. В процессе планирования каждого мероприятия могут принимать участие несколько референтов руководителя, а характеристики мероприятия могут изменяться. После выполнения мероприятия может вводиться резюме, делаться отметка о докладе документа и могут планироваться дальнейшие мероприятия.
План работы руководителя на день и на месяц, а также информация о документах на контроле, должны быть доступны как с рабочих мест референтов, так и с переносного компьютера руководителя (ноутбук), в том числе и без подключения к серверу. Работа с ноутбука без подключения к серверу возможна в ограниченный период времени. Периодически ноутбук должен подключаться к серверу для подкачки изменений.
2.2 Отличительные особенности решения
На каждом рабочем месте создается локальная база данных (ЛБД). В ней содержатся все версии каждого мероприятия, созданные различными участниками в процессе планирования рабочего дня руководителя. Новая версия мероприятия сначала создается некоторым участником в своей ЛБД, затем сохраняется на сервере в упакованном виде, затем подкачивается с сервера другими участниками и записывается в их ЛБД.
Предлагаемая архитектура офисной системы не делает различия между ноутбуком и настольной рабочей станцией в том, что контакт с сервером ограничивается периодической процедурой подкачки, которая может выполняться каждые несколько минут в зависимости от настроек. При выполнении процедуры подкачки происходит обмен с сервером аналогично электронной почте: «свои» изменения записываются из ЛБД на сервер, а «чужие» изменения поступают с сервера в ЛБД. Постоянного контакта офисной системы с сервером не предполагается.
В зависимости от настроек, определяется лимит автономной работы без контакта с сервером. По умолчанию действуют следующие характеристики:
· До 100 новых мероприятий может быть создано в ЛБД без контакта с сервером, с гарантией уникального номера мероприятия.
· До 99 раз каждое мероприятие может редактироваться в ЛБД без контакта с сервером, с сохранением всех версий мероприятия в ЛБД. При редактировании мероприятий в ЛБД возникают версии с дробными номерами.
Сервер документооборота используется как «общая информационная шина», для перекачки планируемых мероприятий между участниками. Хотя описание мероприятия в ЛБД имеет сложную структуру, но на сервере версии описаний мероприятий хранятся в одной реляционной таблице в сжатом виде.
Стыковка с СУД включает «инкрементальную» подкачку документов из СУД в ЛБД, при этом в ЛБД подкачиваются с сервера только новые и измененные версии «нужных» документов.
Офисная система разрабатывается на языках Visual Basic и С++ по технологии СОМ и интегрируется с MS Excel по технологии «надстройки для СОМ-объектов» (COM Add-in). В MS Excel добавляется панель с кнопками и меню для работы с планом работы руководителя.
На рабочей станции создается локальная база данных (ЛБД), в которой аккумулируется вся информация, передаваемая между офисной системой и сервером документооборота, личные настройки пользователя и справочники. Редко изменяемые справочники могут храниться на диске общего пользования в формате XML и также подгружаются в ЛБД.
2.3 План статьи
В разделе 2 описывается создание и хранение версий мероприятий в локальной базе данных (ЛБД). В разделах 3 и 4 описывается хранение версий мероприятий на сервере. В разделе 5 рассматривается инкрементальная подкачка данных с сервера. В разделе 6 содержатся практические рецепты программирования доступа к ЛБД на языке Visual Basic, с использованием библиотеки DbCom[2].
3 Версии мероприятий в ЛБД
3.1 Хранилище мероприятий
01 merop_store:struct // Хранилище мероприятий
Хранилище мероприятий в ЛБД включает основной массив описаний мероприятий и дополнительные индексы. Основной массив имеет два ключа: номер мероприятия и номер версии.
Таблица 1. Основной массив мероприятий
02 merop_array:array // Основной массив
03 merop_struct:struct
04 meropID:double, key // Номер мероприятия, ключ
04 versions:array // Массив версий данного мероприятия
05 version_struct:struct
06 versionID:double, key // Номер версии, ключ
06 merop_info:шаблон -> .as. sh. merop_info // Описание мероприятия
3.2 Описание версии мероприятия
Описание версии мероприятия «merop_info» имеет сложную структуру и включает полную информацию о данной версии мероприятия. Часть этой информации дублируется в дополнительных индексах, см. ниже.
03 merop_info:struct // Описание версии мероприятия
04 simple:struct // Структура для простых атрибутов, для редактора форм
05 meropID:double // Номер мероприятия
05 versionID:double // Номер версии
05 prev_versionID:double // Номер предыдущей версии
05 ver_state:int // Состояние версии мероприятия
05 done:int // Отметка о проведении мероприятия
05 type:int // Тип мероприятия
04 trip:struct // Внешнее мероприятие, визит или командировка
05 trip_type:int // Признак внешнего мероприятия
05 vip:int // Важность мероприятия
05 place:text // Место пребывания
04 stamp: шаблон -> .as. sh. stamp // Кто и когда изменил версию
// Сведения о дате и времени проведения мероприятия
04 timeFrame:шаблон -> .as. sh. timeFrame
04 questions:array // Вопросы
05 question:struct
06 index:int, key // Номер вопроса от 1
06 theme:text // Тема вопроса
06 people:шаблон -> .as. sh. people // Участники по данному вопросу
06 resume:longtext // Резюме по данному вопросу
// Список дальнейших мероприятий
04 next_merops: шаблон -> .as. sh. counted_objectIDs
// Список предыдущих мероприятий
04 prev_merops: шаблон -> .as. sh. counted_objectIDs
// Список первичных версий документов к данному мероприятию
04 primary_docIDs: шаблон -> .as. sh. counted_objectIDs
3.3 Индексирование мероприятий
Для эффективной работы с ЛБД хранилище мероприятий снабжено дополнительными индексами, в которых номера мероприятий проиндексированы по значению свойств мероприятий. Индексы содержат только номера мероприятий, без учета версий. Предполагается, что все индексы согласованно отражают только последнюю версию каждого мероприятия. Имеются следующие индексы:
· merop_states – индекс по состоянию версий мероприятий. Используется для подкачки версий мероприятий с сервера.
· merop_words – полнотекстовый индекс мероприятий по теме и резюме для каждого вопроса. Используется для поиска мероприятий.
· … и другие индексы
Структура индексов следующая:
Таблица 2. Индекс по состоянию версий мероприятий «merop_states»
02 merop_states:array
03 vers_struct:struct
04 ver_state:int, key // Состояние версии мероприятия
// Номера мероприятий, без учета версий
04 meropIDs:шаблон -> .as. sh. counted_objectIDs
Таблица 3. Полнотекстовый индекс мероприятий «merop_words»
02 merop_words:array // Индекс мероприятий по словам
03 word_struct:struct
04 word:text, key // Слово, ключ (в нижнем регистре)
// Номера мероприятий, без учета версий
04 meropIDs:шаблон -> .as. sh. counted_objectIDs
Номера мероприятий содержатся в списке «counted_objectIDs» следующей структуры:
Таблица 4. Шаблон списка кодов объектов со счетчиком «counted_objectIDs»
03 counted_objectIDs:struct // Список кодов объектов со счетчиком
04 count:int // Счетчик объектов
04 objectIDs:array // Список кодов объектов
05 objectID_struct:struct
06 objectID:double, key // Идентификатор объекта
3.4 Состояние версии мероприятия
Версия мероприятия может находиться в одном из следующих состояний:
Таблица 5. Состояние версии мероприятия
Состояние | Обозначение | Описание | Последующие действия |
0 | нет | Обычное состояние | Никаких действий не требуется. |
1 | vers_checked_out | Версия редактируется | По окончании редактирования версия индексируется и переходит в состояние 2. |
2 | vers_want_server | Версия ожидает записи на сервер | При очередном сеансе подкачки версия сохраняется на сервере. |
Мероприятие удалено | При очередном сеансе подкачки удаление мероприятия фиксируется на сервере, см. ниже п. 3 | ||
3 | vers_unread | Версия подкачана с сервера и еще не прочитана пользователем | Пользователь обращает внимание на версию и она переводится в состояние 0. |
Положительные состояния мероприятий заносятся в индекс «merop_states». Каждое положительное состояние означает необходимость некоторых действий с мероприятием, после чего версия переходит в новое состояние.
Последовательность состояний при создании, редактировании и подкачке мероприятий с сервера следующая.
· Новая версия мероприятия создается либо при создании мероприятия, при помощи функции NewMerop, либо в начале редактирования при помощи функции BeginUpdate. Новая версия мероприятия создается в состоянии 1 и мероприятие удаляется изо всех индексов. Исключением является тип мероприятия по документу, которое создается в состоянии 0, см. ниже в п. 2.7.
· По окончании редактирования при помощи функции FinishUpdate состояние 1 сменяется на состояние 2 и мероприятие заносится во все индексы с учетом сделанных изменений при редактировании.
· При записи на сервер состояние 2 сменяется на состояние 0 и мероприятие исключается из индекса по состояниям версий мероприятий «merop_states».
· При подкачке новой «чужой» версии с сервера устанавливается состояние 3, для того чтобы привлечь внимание пользователя к изменениям, сделанным другими пользователями, по аналогии с новыми почтовыми сообщениями. Напротив, «своя» версия при подкачке автоматически переводится в состояние 0.
· Состояние 3 может смениться на состояние 0, если пользователь обратит внимание на новую версию, при этом мероприятие вновь исключается из индекса «merop_states».
3.5 Номера версий мероприятий
Номера версий мероприятий могут быть целыми либо дробными. Дробные номера версий возникают при редактировании мероприятий в ЛБД. При каждой попытке редактирования (BeginUpdate/FinishUpdate) номер версии в ЛБД увеличивается на одну сотую (0.01). Таким образом, до 99 раз мероприятие может редактироваться в ЛБД без контакта с сервером, с сохранением всех версий в ЛБД.
Предположим, что при подкачке с сервера в некоторую ЛБД поступила версия с целым номером N1. Тогда при редактировании версии N1 в данной ЛБД могут возникать версии с номерами (N1+0.01), (N1+0.02),...(N1+0.99). Предположим далее, что после «х» попыток редактирования данный пользователь остановился на версии N1x=(N1+x/100), где 1<=x<=99, после чего в данной ЛБД стартовал очередной цикл подкачки. За это время другими пользователями параллельно могли быть созданы и сохранены на сервере версии с номерами от (N1+1) до M>N1.
При записи версии N1x из данной ЛБД на сервер определяется очередной свободный целый номер версии (M+1)=N2, N2>=N1+1. Версия N1x сохраняется на сервере под номером N2. В том же цикле подкачки версия N2 подкачивается с сервера в ЛБД данного пользователя. Затем, по мере контакта других пользователей с сервером, версия N2 асинхронно подкачивается в другие ЛБД.
При записи на сервер каждой версии присваивается свойство «предыдущая версия», для версии N2 «предыдущей» будет версия N1. Дробные номера версий на сервере не сохраняются. В случае потери ЛБД, с сервера могут быть восстановлены только целые номера версий. Хранение версий мероприятий на сервере подробнее рассматривается ниже, в п. [3].
3.6 Запас свободных номеров мероприятий в ЛБД
При подкачке с сервера в ЛБД создаются несколько интервалов свободных номеров мероприятий. Свободные номера создаются при помощи серверного счетчика, который наращивается через 100 при каждом использовании. Количество интервалов может настраиваться, но обычно достаточно иметь в ЛБД два интервала свободных номеров мероприятий: один текущий, из которого берутся номера для новых мероприятий, и один запасной интервал, содержащий 100 свободных номеров на случай автономной работы без сервера. Таким образом гарантируется, что все создаваемые номера мероприятий различными пользователями будут отличаться и в каждой ЛБД могут быть созданы не менее 100 мероприятий без контакта с сервером.
3.7 Создание мероприятия по документу
При подкачке документа из СУД в каждой ЛБД создается мероприятие специального типа. В каждой ЛБД номер такого мероприятия должен быть одинаковым, поэтому серверный счетчик мероприятий не используется, а номер мероприятия привязывается к первичной версии документа:
meropID = primaryDocID + 0.1,
где meropID есть номер мероприятия по документу, а primaryDocID есть номер первичной версии документа. Дробные номера мероприятий для документов заведомо отличаются от целых номеров обычных мероприятий.
Другая особенность данного типа мероприятий состоит в том, что первая версия мероприятия по документу создается в ЛБД в состоянии 0 и на сервере не сохраняется. При редактировании, например в случае переноса даты доклада, новые версии данного типа мероприятий создаются по общему правилу, изложенному выше в п.2.5. Таким образом, мероприятия по документу могут иметь как дробный номер мероприятия, так и дробный номер версии.
3.8 Редактирование мероприятий
Редактирование мероприятий производится при помощи редактора форм [3]. При редактировании мероприятия выполняются следующие действия:
· Функция BeginUpdate – создает новую версию в хранилище мероприятий в ЛБД с дробным номером версии в состоянии 1. Мероприятие исключается из всех индексов в ЛБД.
· Функция SaveXML – описание версии мероприятия сохраняется из ЛБД в XML-файле.
Вызывается редактор форм, пользователь редактирует мероприятие, XML-файл сохраняется редактором форм после редактирования.
· Функция LoadXML – описание версии мероприятия загружается из XML-файла в ЛБД.
· Функция FinishUpdate – устанавливается состояние 2 и мероприятие заносится в индексы в ЛБД.
В случае отмены редактирования функция CancelUpdate удаляет редактируемую версию мероприятия и восстанавливает исходную версию во всех индексах.
4 Версии мероприятий на сервере
Для хранения версий мероприятий на сервере используется таблица «Мероприятия» следующей структуры:
Таблица 6. Таблица «Мероприятия» на сервере
Название поля | Тип | Назначение |
«Код» | Number | Код записи |
«Мероприятие» | Number | Номер мероприятия |
«Версия» | Number | Номер версии |
«Тело» | BLOB | Информация о мероприятии в сжатом виде |
«Предыдущая версия» | Number | Номер предыдущей версии или null |
Код записи для мероприятия присваивается при помощи сквозного серверного счетчика, который применяется для всех серверных типов объектов, включая документы. Код записи используется для того, чтобы подкачивать новые версии мероприятий с сервера в ЛБД. Для подкачки новых версий мероприятий с сервера достаточно прочесть записи таблицы «Мероприятия» с кодом записи большим, чем последний прочтенный код записи в данной ЛБД.
Информация о мероприятии хранится в поле «Тело» в сжатом виде и представляет собой сжатый XML-файл, подобный тому, который используется при редактировании мероприятий, см. выше п. 2.8.
При сохранении версии мероприятия на сервере создается запись с новым кодом записи, с указанным номером мероприятия, с очередным свободным целым номером версии данного мероприятия и с «телом», содержащим сжатое описание мероприятия. При очередной подкачке с сервера данная версия попадает в ЛБД.
При удалении мероприятия на сервере создается запись с новым кодом записи, с указанным номером мероприятия, но без номера версии и без «тела». При очередной подкачке с сервера такое мероприятие удаляется из ЛБД других пользователей.
5 Версионные серверные объекты СУД
До сих пор мы рассматривали сервер документооборота лишь как «общую информационную шину» для перекачки мероприятий между ЛБД пользователей офисной надстройки. Мероприятия в предлагаемом решении есть объекты офисной надстройки, они создаются и используются в ЛБД, а на сервере хранятся в сжатом виде. Теперь же мы более подробно рассмотрим подкачку в ЛБД «родных» серверных объектов системы управления документооборотом (СУД).
Документы в СУД состоят из нескольких типов объектов, отражающих ограничения реляционной модели:
· Объект «документ» – есть версия регистрационной карточки документа в СУД. Версия документа создается при каждом изменении документа, при этом возникает копия регистрационной карточки, даже если регистрационная информация не изменялась. После снятия с контроля старые версии документа уничтожаются, кроме последней версии.
· Объект «часть» – есть дополнительная запись в составе документа, например: поручение, виза, приложенный файл и т. п. Документ может иметь несколько частей. Части не имеют самостоятельных версий.
· Объект «поручение» – есть запись в контрольной карточке документа, например: назначение задания, изменение срока или исполнителей, отметка контролера о выполнении. Версии поручения отражают ход выполнения данного поручения. Документ может иметь несколько параллельно исполняемых поручений.
Адресная книга СУД также состоит из версионных записей. Запись адресной книги содержит версию «субъекта»: группы либо лица. Субъект может входить в несколько групп. При редактировании адресной книги администратором могут изменяться как отдельные записи, так и структура адресной книги. Структура групп подкачивается полностью, а отдельные измененные записи могут подкачиваться инкрементально.
Между документами могут существовать связи различных типов, например: документ 2 является ответом на документ 1. Связи между документами, связи между исполнителями и поручениями, а также связи между субъектами адресной книги, хранятся в таблице «Связи».
Для всех типов версионных объектов используется сквозной серверный счетчик («счетчик событий»). Код записи для любого типа версионного объекта содержит тип объекта в младших двух цифрах:
objectType = mod(objectID,100)
Серверный «счетчик событий» используется для создания новых кодов записей в таблицах для всех типов объектов. Для каждой версии любого типа объекта в таблице «События» создается запись с одинаковой информацией о версии объекта, в том числе: автор и дата создания версии, дата публикации, а также «Первичная версия». Поле «Первичная версия» в таблице «События» содержит код самой первой версии данного объекта.
5.1 Серверные представления СУД
Система документооборота включает несколько десятков серверных представлений, служащих во-первых, для отчетов, а во-вторых, для подкачки «нужных» документов в ЛБД офисной надстройки. Отметим представление «План контроля», которое включает последнюю версию документов с поручениями, плановый срок выполнения которых либо в будущем, либо не старее заданного дня, например 14 дней назад. Серверные представления полностью пересоздаются каждую ночь, а также инкрементально обновляются в процессе контроля исполнения. План контроля содержит выжимку из документа и два ключа, используемых для подкачки:
· «Первичная версия» – отличает данный документ от других документов. Данный ключ сохраняется неизменным во все время жизни документа, к нему привязывается номер специального типа «мероприятия» для документа в ЛБД.
· «Документ» – текущая версия документа. Возрастает при каждом изменении состояния документа в системе документооборота. Служит для отбора новых документов.
6 Инкрементальная подкачка документов в ЛБД
Термин «инкрементальная подкачка» означает, что в ЛБД подкачиваются с сервера только новые и измененные версии «нужных» документов из системы управления документооборотом.
6.1 Снэпшоты в ЛБД
Термин «снэпшот» (snapshot) обозначает в данной статье мгновенный снимок состояния некоторой серверной таблицы, либо серверного представления, в локальной базе данных.
Структура снэпшота в ЛБД включает следующие элементы:
· Имя снэпшота. Совпадает с именем серверного представления.
· Список полей. Совпадает со списком полей серверного представления. Для каждого поля указывается имя и тип.
· Матрица значений: список записей и для каждой записи список полей записи. Все значения хранятся в текстовом виде.
· Сведения о последней синхронизации с сервером:
o Дата и время выполнения запроса на сервере и на клиентской машине
o Серверный «счетчик событий» в момент выполнения запроса. Это сквозной счетчик для всех типов серверных объектов.
o Длительность выполнения запроса и длительность считывания записей в ЛБД.
· Индекс по состоянию записей. При подкачке в него заносятся номера новых и измененных записей.
· Индексы по различным полям. Каждый индекс содержит значение поля и список номеров записей снэпшота с таким значением данного поля.
Список полей, по которым нужно индексировать данный снэпшот, формы запросов для создания и для инкрементального обновления снэпшота включены в настройки системы.
6.2 Инкрементальное обновление снэпшота
При подкачке снэпшота с сервера в ЛБД, формируется запрос на языке SQL, который отбирает записи указанного серверного представления со значением поля «Документ», большим чем значение серверного счетчика событий в момент предыдущей подкачки.
Затем запрос выполняется и просматриваются записи результата. Для каждой записи результата, при помощи индекса снэпшота по полю «Первичная версия» находится номер записи снэпшота в ЛБД, где содержится данный документ. Затем старая запись снэпшота удаляется, а новая запись результата заносится в конец матрицы значений снэпшота с новым номером записи и индексируется.
6.3 Серверные процедуры
Система документооборота включает серверные процедуры для действий с документами и поручениями, которые могут вызываться из Visual Basic, включая следующие:
· Процедура определения состава документа составляет список частей и поручения, относящихся к данной версии документа.
· Процедура чтения атрибутов выдает список атрибутов для заданного списка объектов.
· Процедура расширения списка документов дополняет список документов всеми связанными документами.
6.4 Подкачка документов с сервера в ЛБД
При подкачке документов с сервера в ЛБД выполняются следующие действия:
· Обновляется снэпшот «План контроля», включающий «нужные» документы.
· При помощи индекса новых и измененных записей снэпшота составляется список новых и измененных документов.
· Список расширяется связанными документами при помощи серверной процедуры.
· Документы и их атрибуты считываются с сервера при помощи серверных процедур.
· Новые версии серверных объектов и их атрибуты записываются в ЛБД.
· Атрибуты объектов заносятся в атрибутную справочную в ЛБД.
6.5 Атрибуты объектов в ЛБД
Все серверные типы объектов размещаются в ЛБД в общем массиве объектов. Объекты загружаются с сервера в виде списка атрибутов. Список атрибутов объекта может включать множественные атрибуты и группы связанных атрибутов.
Для эффективного поиска объектов в ЛБД создается «атрибутная справочная». При загрузке объектов с сервера в ней формируются списки кодов объектов, сгруппированные по значению различных атрибутов.
6.6 Адресная книга СУД в ЛБД
Записи адресной книги СУД заносятся в ЛБД как отдельные объекты. Для каждого объекта формируются списки связанных объектов, сгруппированные по типу связи. Типы связей в адресной книге следующие:
Таблица 7. Типы связей в адресной книге в ЛБД.
Тип связи | Обозначение | Назначение |
1 | link_type_group | Группы, в которые непосредственно входит данный субъект |
2 | link_type_child | Непосредственный состав данной группы: обратный тип связи к "link_type_group" |
3 | link_type_far_group | Дальние включающие группы, исключая непосредственное включение |
4 | link_type_far_member | Дальние потомки данной группы, исключая непосредственное подчинение |
Для инкрементальной подкачки адресной книги используется серверное представление «Группы», которое включает записи для каждой пары «группа» – «член группы», как для непосредственно подчиненных членов группы, так и для косвенно подчиненных, через другие группы. В каждой записи указывается как первичная, так и текущая версия группы и члена группы.
Подкачка адресной книги происходит в следующей последовательности:
· Определяется необходимость подкачки групп по дате изменения серверного представления «Группы».
· Подкачка групп включает следующие шаги:
o Удаляются все связи в адресной книге в ЛБД
o Удаляется снэпшот «Группы» в ЛБД
Шаг загрузки снэпшота «Группы» выполняется ниже, после загрузки субъектов.
· Формируется запрос для получения измененных субъектов с момента прошлой подкачки.
· Субъекты загружаются с сервера, а их атрибуты заносятся в атрибутную справочную.
· В случае подкачки групп загружается снэпшот «Группы».
· Просматривая записи снэпшота «Группы», создаются связи в адресной книге.
7 Использование библиотеки DbCom
В этом разделе описываются практические рецепты использования библиотеки DbCom для работы с ЛБД на языке Visual Basic. Технология использования библиотеки DbCom включает трансляцию описания данных при помощи программы Credod. При трансляции описания данных Schema. txt возникают следующие файлы:
· Schema. dod – файл дерева описания данных (ДОД) Ники.
· Schema. dll – скомпилированные классы С++ для всех нетерминальных вершин ДОД.
· В директории «с++» генерируются заголовочные файлы для базовых и пользовательских классов с++ для всех нетерминальных вершин ДОД. Базовые классы перегенерируются при каждом изменении и трансляции схемы, а пользовательские классы, производные от базовых, сохраняются и могут быть вручную дополнены функциями для программирования доступа к ЛБД на языке с++.
Кроме того в данном методе доступа используются библиотеки Database. dll и DbCom. dll. Непосредственно в программе на языке Visual Basic используются только объекты, предоставляемые библиотекой DbCom.
7.1 Типы СОМ-объектов в библиотеке DbCom
При программировании на языке Visual Basic используются следующие СОМ-объекты из библиотеки DbCom:
· Database – содержит функции для получения корневой структуры схемы и вспомогательные функции для работы с ЛБД. Например, метод Database. Save сохраняет из памяти в ЛБД все СОМ-объекты из библиотеки DbCom.
· Structure – отвечает структурной вершине ЛБД. Позволяет получить непосредственно подчиненные вершины по имени, через точку как принято в VB: myStruct. myElement1, myStruct. myElement2.
· Array – отвечает массиву в ЛБД. Позволяет находить элемент по ключу в скобках: myArray(myKey1), myArray(myKey2), а также выполнять циклы по массиву «for each myStruct in myArray»
· Terminal – отвечает терминальной вершине, отвечает за преобразование значений из формата Visual Basic в формат Ники: myString = myStruct. myElement. Обычно переменных этого типа в программе не требуется, поскольку обращение к ним носит мимолетный характер и все происходит незаметно по правилам Visual Basic.
· Vertex – вспомогательный интерфейс, отвечающий вершине любого типа. Используется например, для удаления вершины в ЛБД: myStruct. zzVertex. Delete, myArray. Vertex. Delete (не путать с myArray. Clear – очистка массива). Но: myTerminal. Delete.
Интерфейс Vertex удобен для отладки, поскольку показывает ключ вершины в дереве и привязку к ДОД. В отладчике Visual Basic переменные типов Structure/Array/Terminal показывают свойство Structure. zzVertex, Array. Vertex, Terminal. Vertex. Префикс «zz» в «zzVertex» отличает свойство структуры от элементов структуры.
Далее мы будем для краткости именовать типы объектов Structure, Array, Terminal и Vertex собирательным термином «хранимые объекты».
7.2 Загрузка хранимого объекта из ЛБД в память
Элемент массива загружается по требованию, либо при указании явного ключа, либо в цикле по массиву. Структура загружается полностью, вместе с подчиненными терминальными вершинами, структурами и их подчиненными подструктурами и их терминальными вершинами, но только до массивов. Вложенный массив – тип Array – загружается в память вместе с охватывающей структурой, однако элементы массива в память не загружаются, до тех пор пока они не потребуются: либо по ключу, либо пока не начнется цикл по данному вложенному массиву.
7.3 Время жизни хранимого объекта в памяти
Как любой СОМ-объект, хранимые объекты обладают стандартным счетчиком использования, который автоматически поддерживается исполняющей системой Visual Basic. Счетчик использования включает:
· По 1 за каждый явный указатель на данный объект. Явные указатели хранятся в переменных Visual Basic типов Object, Variant, Structure, Array, Terminal, Vertex.
· По 1 за каждый охватывающий оператор With с траекторией, проходящей через данную вершину. Подробнее это положение разъясняется ниже.
Специальный метод Vertex. Trash принудительно удаляет из памяти данную вершину и все ее подчиненные. Информация сохраняется в ЛБД и удаляется из памяти. После этого указатели на данную вершину и подчиненные вершины использовать нельзя, прежде следует их заново инициализировать.
7.3.1 Использование указателей на хранимые объекты в bas-файлах
В начале bas-файла размещаем указатели на ветви ЛБД, которые нужны в данном модуле:
Private m_merop_store As DBCOMLib. Structure
Private m_future_merops As DBCOMLib. Structure
Private m_done_merops As DBCOMLib. Structure
...
Для инициализации переменных применяем процедуру MyModuleInit:
Public Sub MyModuleInit(db As DBCOMLib. Database)
' Инициализировать модуль
On Error Resume Next
With db. Root
Set m_merop_store = .merop_store
Set m_future_merops = .future_merops
Set m_done_merops = .done_merops
End With
End Sub
В этом примере db. Root означает корень ЛБД, «merop_store», «future_merops» и «done_merops» - ветви верхнего уровня. Оператор With означает, что точка перед именем ветви вставляется после db. Root, что эквивалентно следующей записи:
Set m_merop_store = db. Root. merop_store
Set m_future_merops = db. Root. future_merops
Set m_done_merops = db. Root. done_merops
7.3.2 Использование указателей на хранимые объекты в cls-файлах
В cls-файлах можно применять процедуру Init такого же вида, что и процедура MyModuleInit в предыдущем пункте.
7.4 Прямая утилизация хранимых объектов – метод «Vertex. Trash»
Термином «утилизация» обозначается использование метода Vertex. Trash. При этом из памяти удаляется данная вершина и все ее подчиненные, но предварительно все изменения сохраняются в ЛБД. После этого все указатели на данную вершину и ее подчиненные в памяти теряют силу. Для сохранения изменений имеется также метод Vertex. Save, не удаляющий ничего из памяти. Не следует путать утилизацию памяти при помощи метода Trash с удалением данных из ЛБД при помощи метода Delete.
Использование прямой утилизации рекомендуется в следующих случаях:
· Для того чтобы гарантировать конец работы с данной вершиной и ее поддеревом в вашей программе.
· Для того чтобы гарантировать перезагрузку в память из ЛБД после работы с Никой в обход библиотеки DbCom. Пример: загрузка поддерева в Нику из XML-файла, затем утилизация указателя на вершину. После утилизации любое обращение к данной вершине в Visual Basic вызовет загрузку в память из Ники.
7.5 Перезагрузка в память из ЛБД
Метод Vertex. Reload выполняет перезагрузку вершины из ЛБД в память. Применяется после
7.6 Отложенная запись хранимых объектов из памяти в ЛБД
Запись в ЛБД выполняется не сразу при изменении терминальной вершины в Visual Basic. Неявная запись в ЛБД выполняется при удалении охватывающего элемента массива из памяти. Явная запись в ЛБД происходит при выполнении методов Save или Trash: либо для данной вершины, либо для вышестоящей «родительской» вершины на одном из верхних уровней, либо для всей базы данных: Database. Save.
Неявная отложенная запись в ЛБД может привести к неожиданным эффектам, если вы планируете работу в Никой в обход библиотеки DbCom, например для сохранения поддерева из Ники в XML-файл. Рекомендуется предварительно сохранить все изменения при помощи метода Database. Save.
7.7 Искусственное создание вершин в ЛБД
Создание вершин происходит при сохранении непустых терминальных значений либо ключей. При создании или загрузке структуры из ЛБД в память, каждая структура полностью развертывается в памяти вместе с подчиненными подструктурами, но новые элементы структуры при этом не создаются:
Set myStruct = myArray. Add(myKey)
myStruct. myInnerStruct. myString = myString
В этом примере подструктура myInnerStruct и терминальная вершина myString создаются в ЛБД только если переменная myString есть непустая строка. Одного факта обращения к myInnerStruct в программе недостаточно для того, чтобы эта вершина создалась. Для того, чтобы создать подструктуру в ЛБД, нужно либо записать значение в ее элемент, либо создать элемент вложенного массива, при помощи функции Add:
Set myInnerElement = myStruct. myInnerStruct. myInnerArray. Add(myKey)
Эти тонкости могут иметь значение в том случае, если нужно например, скопировать ветвь ЛБД, см. ниже. Перед копированием нужно обеспечить существование целевой вершины.
7.8 Копирование поддерева
Метод Vertex. CopyFrom позволяет скопировать поддерево в ЛБД. После копирования целевая вершина удаляется из памяти (утилизируется)! Ее следует затем перезагрузить. Последовательность операций для копирования подструктуры в общем случае следующая:
· Создать целевую подструктуру, если нужно, искусственно, см. предыдущий пункт.
· myInnerStruct. zzVertex. CopyFrom – скопировать поддерево в целевую вершину. При этом myInnerStruct удаляется из памяти.
· myStruct. zzVertex. Reload – перезагрузить охватывающую структуру. При этом также загружается и подструктура.
· Инициализировать указатели на целевую копию подструктуры.
7.9 Обработка вложенных массивов в ЛБД
Как отмечалось выше, элементы массивов загружаются в память либо при указании ключа, либо в цикле по массиву. Вложенные операторы WITH являются наиболее удобным способом доступа к вложенным массивам с указанием ключей, как при чтении из ЛБД, так и при записи в ЛБД. Вложенные операторы цикла «FOR EACH» поддерживаются библиотекой DbCom наряду с методом Array. Restrict для ограничения интервала просмотра ключей массива.
7.9.1 Траектории для доступа к данным
· Если нужно прочесть либо записать только одно значение из-под вложенного массива, то вполне можно написать одну длинную траекторию:
myString = db. Root. myArray1(mykey1). _
myArray2(mykey2).myInnerStruct. myString
При доступе к данным нет ограничений на длину траектории.
· Напротив, если нужно получить указатель на элемент вложенного массива, то обязательно следует сохранить и указатель на элемент охватывающего массива:
set myStruct1 = db. Root. myArray1(mykey1) ' ПРАВИЛЬНО
set myStruct2 = myStruct1.myArray2.add(mykey2) ' ПРАВИЛЬНО
· Было бы неправильно написать так:
set myStruct2 = db. Root. myArray1(mykey1).myArray2.add(mykey2) 'НЕПРАВИЛЬНО!
В данном случае элемент верхнего массива удалился бы из памяти прежде присвоения переменной.
· Было бы неправильно написать и так:
set myStruct2 = myStruct1.myArray2.add(mykey2).myInnerStruct 'НЕПРАВИЛЬНО!
В данном случае элемент массива также удалился бы из памяти прежде присвоения переменной.
· Если охватывающий элемент массива по любой причине удаляется из памяти, то вместе с ним удаляются из памяти и все элементы вложенного массива, после чего указатели на элементы вложенного массива использовать нельзя:
with db. Root. myArray1(mykey1) ' ПРАВИЛЬНО
set myStruct2 =.myArray2.add(mykey2) ' ПРАВИЛЬНО
myStruct2.myString = myString ' ПРАВИЛЬНО
end with
myString = myStruct2.myString ' НЕПРАВИЛЬНО: mykey1 и myStruct2 уже
' удалены из памяти
Мнемонические правила для получения указателей с помощью траектории следующие:
· Траектория должна соответствовать структуре ЛБД.
· В одной траектории можно указывать не более одного ключа массива в скобках.
· Ключ массива в скобках можно указывать только в конце траектории.
Аналогичные правила применимы и к вложенным операторам WITH, см. ниже.
7.9.2 Вложенные операторы WITH для чтения и записи хранимых данных
Общий вид оператора WITH для доступа к хранимым данным следующий:
WITH [переменная][.простая траектория][.add][(ключ)]
Элементы оператора WITH следующие:
· переменная – объектная переменная, указывающая на некоторую структуру или массив ЛБД.
· простая траектория – траектория, состоящая из одного или нескольких имен через точку, но без скобок, то есть без ключей. Каждое звено траектории может отвечать только элементу структуры, но не элементу массива.
· .add – функция для создания элемента массива. Перед нею должен быть массив.
· (ключ)– ключ массива в скобках. Перед ключом должен быть массив.
В исполняющей системе Visual Basic оператору WITH соответствует неявный временный указатель. Поэтому оператор WITH подчиняется тем же правилам, которые изложены выше для указателей:
· Структура вложенных операторов WITH должна соответствовать структуре ЛБД.
· В одном операторе WITH можно указывать не более одного ключа массива в скобках.
· Ключ массива в скобках можно указывать только в конце оператора WITH.
Пример:
with db. Root
with. myArray1(mykey1) ' Поиск элемента верхнего массива
with. myArray2.add(mykey2) ' Создание элемента вложенного массива
with. myInnerStruct ' Отдельный оператор WITH для подструктуры
.myString = "abc" ' Запись значения в ЛБД
.myNumber = 987.65 ' Запись значения в ЛБД
end with
end with
end with
end with
Операторы WITH не удерживают указатели на промежуточные элементы траектории. Неправильно было бы написать
with .myArray2.add(mykey2).myInnerStruct ' НЕПРАВИЛЬНО !
В этом случае элемент массива удалился бы из памяти прежде чем нужно.
7.9.3 Циклы по хранимым массивам
Перед тем как начинать цикл по массиву, можно определить интервал просмотра ключей при помощи метода Array. Restrict:
myArray. Restrict FromKey, ToKey, ExcludeLeft, ExcludeRight
Параметры метода следующие:
· FromKey – начальный ключ.
· ToKey – конечный ключ, который должен быть не меньше начального.
· ExcludeLeft – укажите TRUE, если начальный ключ нужно пропустить. По умолчанию FALSE.
· ExcludeRight – укажите TRUE, если конечный ключ нужно исключить. По умолчанию FALSE.
Если метод Restrict не используется, то массив просматривается от начала до конца. Метод Restrict действует на один ближайший цикл по данному массиву. Следующий цикл по тому же массиву будет выполняться так, как если бы метод Restrict не вызывался.
Переменная цикла, как всегда в Visual Basic, должна быть объектного типа: Object, Variant, Structure, Terminal, Vertex. Пример:
Таблица 8. Пример цикла по хранимому массиву
Dim person As DBCOMLib. Structure
Dim people As String, s As String
Dim CountPeople As Long, n As Long
With m_info
With. questions(Index)
CountPeople = .people. Last. zzKey
For Each person In .people
With person
s = .name
End With
people = people & s
If CountPeople > n Then people = people & ", "
n = n + 1
Next person
End With
End With
7.10 Работа с ЛБД помимо библиотеки DbCom
· Свойство Database. hAccess возвращает указатель на таблицу ACCESS для текущей точки в корне ЛБД, с помощью которой ЛБД становится доступной для программ, написанных на С/С++ на уровне СУБД Ника [4]. Например в предлагаемом решении таким способом подключается компонента NikaFormDrvBase, которая входит в состав редактора форм [3] и осуществляет сохранение данных их ЛБД в XML-файл и восстановление из хмл-файла в ЛБД.
· Свойство Vertex. Path возвращает составной путь от корня ЛБД до данной вершины, через указанный разделитель.
Перед вызовом внешней компоненты рекомендуется сохранить изменения из памяти в ЛБД, а после внешнего изменения ЛБД рекомендуется выполнить перезагрузку в память из ЛБД, как описано выше.
Литература
1. Архитектура серверной части системы документооборота. Е. Плискин, В. Слышкин. В сб.: «Методы и средства работы с документами», Институт системного анализа РАН, 2000 г.
2. Документный метод доступа к иерархической базе данных. Е. Плискин. В сб.: «Управление информационными потоками», Институт системного анализа РАН, 2002 г.
3. Представление структурированных информационных объектов в виде электронных форм. Б. Романов. Там же.
4. Системы управления базами данных и знаний: Справ. изд. / , , и др.; Под ред. . М.: Финансы и статистика, 1991.


