Creatio development guide
PDF
Это документация Creatio версии 7.16.0. Мы рекомендуем использовать новую версию документации.

Объектная модель хранилищ Creatio

Glossary Item Box

Классы и интерфейсы Creatio для работы с хранилищем данных и кэшем

Для работы с хранилищем данных и кэшем в Creatio реализован ряд классов и интерфейсов, которые расположены в пространстве имен Terrasoft.Core.Store ("Библиотеки классов серверной части ядра платформы"). Ниже кратко перечислены основные из них.

Базовое хранилище IBaseStore

Базовые возможности всех типов хранилищ определяет интерфейс IBaseStore. Свойства и методы этого интерфейса реализуют:

  • Доступ к данным по ключу для чтения/записи (индексатор this[string key]).
  • Удаление данных из хранилища по заданному ключу (метод Remove(string key)).
  • Инициализация хранилища заданным списком параметров (метод Initialize(IDictionary parameters)). На текущий момент параметры для инициализации хранилищ Creatio вычитываются из конфигурационного файла. Списки параметров задаются в секциях storeDataAdapter (для хранилища данных), storeCacheAdapter (для кэша). Но в общем случае параметры могут задаваться произвольным образом.

Хранилище данных IDataStore

Интерфейс определяет специфику работы с хранилищами данных. Является наследником базового интерфейса хранилищ IBaseStore. Дополнительно в интерфейсе определена возможность получения списка всех ключей хранилища (свойство Keys).

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

Хранилище кэша ICacheStore

Интерфейс определяет специфику работы с кэшами. Является наследником базового интерфейса хранилищ IBaseStore. В интерфейсе определено свойство GetValues(IEnumerable keys), которое возвращает словарь объектов кэша с заданными ключами. Данный метод позволяет оптимизировать работу с хранилищем при одновременном получении набора данных.

Класс Store

Статический класс для доступа к кэшам и хранилищам данных различных уровней. Уровни хранилища данных и кэша определены в перечислениях Terrasoft.Core.Store.DataLevel и Terrasoft.Core.Store.CacheLevel соответственно (см. табл. 1 и 2).

Класс Store имеет два статических свойства:

  • Свойство Data возвращает экземпляр провайдера хранилища данных.
  • Свойство Cache возвращает экземпляр провайдера кэша.

В примере 1 продемонстрирована работа с кэшем и хранилищем данных с использованием класса Store.

Для обеспечения миграции от фреймворка ASP.NET Framework к ASP.Net Core начиная с версии приложения 7.14.2 изменился способ работы с хранилищами данных уровня Session и Request. Для корректной работы хранилищ в ASP.Net Core необходимо заменить использование статических свойств на работу через UserConnection (см. ниже)

Пример 1

// Внимание! Код некорректный начиная с версии 7.14.2.!
// Получение ссылки на хранилище данных приложения уровня сессии. 
IDataStore dataStore = Store.Data[DataLevel.Session];

// Помещение в хранилище данных значения "Data Test Value" с ключом "DataKey".
dataStore["DataKey"] = "Data Test Value";

// Получение ссылки на кэш приложения уровня рабочего пространства.
ICacheStore cacheStore = Store.Cache[CacheLevel.Workspace];

// Удаление из кэша элемента с ключом "CacheKey".
cacheStore.Remove("CacheKey");

Доступ к хранилищам данных и кэшам из UserConnection

Доступ к хранилищам данных и кэшам приложения из конфигурационного кода можно получить, используя свойства статического класса Store пространства имен Terrasoft.Core.Store. Альтернативным вариантом доступа к хранилищу данных и кэшу в конфигурационной логике, который позволяет избежать использования длинных имен свойств и подключения дополнительных сборок, является доступ через экземпляр класса UserConnection.

В классе UserConnection реализован ряд вспомогательных свойств, позволяющих получить быстрый доступ к хранилищам данных и кэшу различных уровней:

  • ApplicationCache возвращает ссылку на кэш уровня приложения.
  • WorkspaceCache возвращает ссылку на кэш уровня рабочего пространства.
  • SessionCache возвращает ссылку на кэш уровня сессии.
  • RequestData возвращает ссылку на хранилище данных уровня запроса.
  • SessionData возвращает ссылку на хранилище данных уровня сессии.
  • ApplicationData возвращает ссылку на хранилище данных уровня приложения.

В большинстве случаев обращение к свойствам UserConnection идентично обращениям к свойствам Store.Cache и Store.Data с указанием соответствующих уровней. Однако в некоторых ситуациях (например, при запуске бизнес-процессов с помощью планировщика) может использоваться другая реализация. Поэтому в конфигурационной логике для доступа к хранилищам рекомендуется использовать свойства объекта UserConnection.

Для обеспечения миграции от фреймворка ASP.NET Framework к ASP.Net Core начиная с версии приложения 7.14.2 изменился способ работы с хранилищами данных уровня Session и Request. Для корректной работы хранилищ в ASP.Net Core необходимо заменить использование статических свойств на работу через UserConnection

Пример 2

// Ключ, с которым в кэш будет помещаться значение.
string cacheKey = "SomeKey";

// Помещение значения в кэш уровня сессии через свойство UserConnection.
UserConnection.SessionCache[cacheKey] = "SomeValue";

// Получение значения из кэша через свойство класса Store.
// В результате переменная valueFromCache будет содержать значение "SomeValue".
string valueFromCache = UserConnection.SessionCache[cacheKey] as String;

Использование кэша в EntitySchemaQuery

В EntitySchemaQuery реализован механизм работы с хранилищем (кэшем Creatio либо произвольным хранилищем, определенным пользователем). Работа с кэшем позволяет оптимизировать эффективность выполнения операций за счет обращения к закэшированным результатам запроса без дополнительного обращения к базе данных. При выполнении запроса EntitySchemaQuery данные, полученные из базы данных на сервере, помещаются в кэш, который определяется свойством Cache с ключом, который задается свойством CacheItemName. По умолчанию в качестве кэша запроса EntitySchemaQuery выступает кэш Creatio уровня сессии с локальным хранением данных. В общем случае в качестве кэша запроса может выступать произвольное хранилище, которое реализует интерфейс ICacheStore.

Ниже приведен пример работы с кэшем приложения при выполнении запроса EntitySchemaQuery (пример 3). В примере строится запрос, который возвращает список всех городов схемы City. При получении результатов выполнения запроса (после вызова метода GetEntityCollection()) эти результаты помещаются в кэш, откуда затем могут использоваться при повторном получении коллекции элементов запроса без дополнительного обращения к базе данных.

Пример 3

// Создание экземпляра запроса EntitySchemaQuery с корневой схемой City.
var esqResult = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "City");

// Добавление в запрос колонки с наименованием города.
esqResult.AddColumn("Name");

// Определение ключа, под которым в кэше будут храниться результаты выполнения запроса.
// В качестве кэша выступает кэш уровня сессии с локальным кэшированием данных (так как не 
// переопределяется свойство Cache объекта).
esqResult.CacheItemName = "EsqResultItem";

// Выполнение запроса к базе данных для получения результирующей коллекции объектов.
// После выполнения этой операции результаты запроса будут помещены в кэш. При дальнейшем обращении к 
// esqResult для получения коллекции объектов запроса (если сам запрос не был изменен) эти объекты будут 
// браться из сессионного кэша.
esqResult.GetEntityCollection(UserConnection);  

Прокси-классы хранилища и кэша

Понятие и назначение прокси-классов

Доступ к хранилищам и кэшам в Creatio может быть осуществлен как напрямую (через свойства класса Store), так и через прокси-классы.

Прокси-классы — это специальные объекты, которые представляют собой промежуточное звено между хранилищами и вызывающим кодом. Прокси-классы позволяют выполнять промежуточные действия над данными перед их чтением/записью в хранилище. Особенностью прокси-классов является то, что каждый из них является хранилищем.

Области применения прокси-классов

1. Первоначальная настройка и конфигурирование приложения

В конфигурационном файле Web.config можно настроить использование прокси-классов для хранилищ данных и кэшей. Настройка прокси-классов для соответствующего хранилища данных или кэша осуществляется в секциях storeDataAdapter и storeCacheAdapter соответственно. В них добавляется секция proxies, в которой перечисляются все прокси-классы, применяемые к хранилищу (пример 4).

Пример 4

<storeDataAdapters>
    <storeAdapter levelName="Request" type="RequestDataAdapterClassName">
        <proxies>
            <proxy name="RequestDataProxyName1" type="RequestDataProxyClassName1" />
            <proxy name="RequestDataProxyName2" type="RequestDataProxyClassName2" />
            <proxy name="RequestDataProxyName3" type="RequestDataProxyClassName3" />
        </proxies>
    </storeAdapter>
</storeDataAdapters>

<storeCacheAdapters>
    <storeAdapter levelName="Session" type="SessionCacheAdapterClassName">
        <proxies>
            <proxy name="SessionCacheProxyName1" type="SessionCacheProxyClassName1" />
            <proxy name="SessionCacheProxyName2" type="SessionCacheProxyClassName2" />
        </proxies>
    </storeAdapter>
</storeCacheAdapters> 

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

При этом необходимо учитывать следующее:

  • "Конечной точкой" применения цепочки прокси-классов является конкретный кэш или хранилище данных, для которого эта цепочка определяется.
  • Отдельно взятый прокси-класс знает, с каких кэшем или хранилищем он работает — ссылка на него определяется свойствами ICacheStoreProxy.CacheStore или IDataStoreProxy.DataStore. Однако, на что именно ссылается это свойство (на другой прокси-класс, на конечное хранилище или кэш), для прокси-класса неизвестно. При этом сам прокси может выступать в качестве хранилища, с которым будут работать другие прокси-классы.

Так, в соответствии с настройками, приведенными в примере 4, цепочка выполнения прокси-классов, например, хранилища данных, будет следующей: RequestDataProxyName3 —> RequestDataProxyName2 —> RequestDataProxyName1 —> RequestDataAdapterClassName (конечное хранилище данных уровня запроса).

2. Разграничение данных различных пользователей приложения

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

3. Выполнение других промежуточных действий с данными перед помещением их в хранилище

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

Базовые интерфейсы прокси-классов

Чтобы класс можно было использовать как прокси для работы с хранилищами, он должен реализовывать один или оба интерфейса пространства имен Terrasoft.Core.Store:

  • IDataStoreProxy — интерфейс прокси-классов хранилища данных.
  • ICacheStoreProxy — интерфейс прокси-классов кэша.

Каждый из этих интерфейсов имеет одно свойство — ссылку на то хранилище (или кэш), с которым работает данный прокси-класс. Для интерфейса IDataStoreProxy это свойство DataStore, а для интерфейса ICacheStoreProxy — свойство CacheStore.

Прокси-классы трансформации ключей

В Creatio реализован ряд прокси-классов, реализующих логику трансформации ключей значений, помещаемых в хранилища.

1. Класс KeyTransformerProxy

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

2. Класс PrefixKeyTransformerProxy

Прокси-класс, преобразующий ключи кэша путем добавления к ним заданного префикса.

В примере 5 демонстрируется работа с кэшем уровня сессии через прокси-класс PrefixKeyTransformerProxy.

Пример 5

// Ключ, с которым значение будет помещаться в кэш через прокси.
string key = "Key";

// Префикс, который будет добавляться к ключу значения прокси-классом.
string prefix = "customPrefix";

// Создание прокси-класса, который будет использоваться для записи значений в кэш уровня сессии.
ICacheStore proxyCache = new PrefixKeyTransformerProxy(prefix, Store.Cache[CacheLevel.Session]);

// Запись значения с ключом key в кэш через прокси-класс. 
// Фактически это значение записывается в глобальный кэш уровня сессии с ключом prefix + key. 
proxyCache[key] = "CachedValue";

// Получение значения по ключу key через прокси.
var valueFromProxyCache = (string)proxyCache[key];

// Получение значения по ключу prefix + key непосредственно из кэша уровня сессии.
var valueFromGlobalCache = (string)UserConnection.SessionCache[prefix + key]; 

В итоге переменные valueFromProxyCache и valueFromGlobalCache будут содержать одинаковое значение "CachedValue".

3. Класс DataStoreKeyTransformerProxy

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

В примере 6 демонстрируется работа с хранилищем данных через прокси-класс DataStoreKeyTransformerProxy.

Пример 6

// Ключ, с которым значение будет помещаться в хранилище через прокси.
string key = "Key";

// Префикс, который будет добавляться к ключу значения прокси-классом.
string prefix = "customPrefix";

// Создание прокси-класса, который будет использоваться для записи значений в хранилище уровня сессии.
IDataStore proxyStorage = new DataStoreKeyTransformerProxy(prefix) { DataStore = Store.Data[DataLevel.Session] };

// Запись значения с ключом key в хранилище через прокси-класс. 
// Фактически это значение записывается в глобальное хранилище уровня сессии с ключом prefix + key.
proxyStorage[key] = "StoredValue";

// Получение значения по ключу key через прокси.
var valueFromProxyStorage = (string)proxyStorage[key];

// Получение значения по ключу prefix + key непосредственно из хранилища уровня сессии.
var valueFromGlobalStorage = (string)UserConnection.SessionData[prefix + key]; 

В итоге переменные valueFromProxyStorage и valueFromGlobalStorage будут содержать одинаковое значение "StoredValue".

Локальное кэширование данных

На базе прокси-классов в Creatio реализован механизм локального кэширования данных. Основная цель кэширования данных — снижение нагрузки на сервер хранения данных и времени выполнения запросов при работе с редко изменяемыми данными.

Логику механизма локального кэширования реализует внутренний прокси-класс LocalCachingProxy. Этот прокси-класс выполняет кэширование данных на текущем узле web-фермы. Класс выполняет мониторинг времени жизни кэшированных объектов и получает данные из глобального кэша только в том случае, если кэшированные данные не актуальны.

Для применения механизма локального кэширования на практике используются методы расширения для интерфейса ICacheStore из статического класса CacheStoreUtilities:

  • WithLocalCaching() — переопределенный метод, который возвращает экземпляр класса LocalCachingProxy, выполняющего локальное кэширование.
  • WithLocalCachingOnly(string) — метод, выполняющий локальное кэширование данных заданной группы элементов с мониторингом их актуальности.
  • ExpireGroup(string) — метод устанавливает признак устаревания для заданной группы элементов. При вызове этого метода все элементы заданной группы становятся неактуальными и не возвращаются при запросе данных.

В примере 7 демонстрируется работа с кэшем рабочего пространства с использованием локального кэширования.

Пример 7

// Создание первого прокси-класса, который выполняет локальное кэширование данных. Все элементы, 
// записываемые в кэш через этот прокси, принадлежат к группе контроля актуальности Group1. 
ICacheStore cacheStore1 = Store.Cache[CacheLevel.Workspace].WithLocalCaching("Group1");

// Добавление элемента в кэш через прокси-класс.
cacheStore1["Key1"] = "Value1";

// Создание второго прокси-класса, который выполняет локальное кэширование данных. Все элементы, 
// записываемые в кэш через этот прокси, также принадлежат к группе контроля актуальности Group1. 
ICacheStore cacheStore2 = Store.Cache[CacheLevel.Workspace].WithLocalCaching("Group1");
cacheStore2["Key2"] = "Value2";

// Для всех элементов группы Group1 устанавливается признак устаревания. Устаревшими считаются элементы 
// с ключами Key1 и Key2, так как они принадлежат к одной группе контроля актуальности Group1, несмотря на 
// то, что добавлены в кэш через разные прокси.
cacheStore2.ExpireGroup("Group1");

// Попытка получения значений из кэша по ключам Key1 и Key2 после того, как эти элементы были помечены как 
// устаревшие. В результате переменные cachedValue1 и cachedValue2 будут содержать значение null. 
var cachedValue1 = cacheStore1["Key1"]; 
var cachedValue2 = cacheStore1["Key2"];
© Terrasoft 2002-2020.

Был ли данный материал полезен?

Как можно улучшить эту статью?