Событийный слой объекта
Glossary Item Box
Общие сведения
В версии 7.12.4 появилась возможность разрабатывать бизнес логику объектов без использования событийных подпроцессов.
Механизм событийного слоя Entity срабатывает после выполнения событийных подпроцессов объекта.
Чтобы добавить требуемые действия в обработчик нужного события объекта (наследника класса Entity), необходимо:
- Создать класс, наследующий BaseEntityEventListener.
- Декорировать класс атрибутом EntityEventListener с указанием имени сущности, для которой необходимо выполнить подписку событий.
- Переопределить метод-обработчик нужного события.
Например:
// Слушатель событий сущности "Активность". [EntityEventListener(SchemaName = "Activity")] public class ActivityEntityEventListener : BaseEntityEventListener { // Переопределение обработчика события сохранения сущности. public override void OnSaved(object sender, EntityAfterEventArgs e) { // Вызов родительской реализации. base.OnSaved(sender, e); //... } }
Классы, образующие механизм событийного слоя Entity
Класс BaseEntityEventListener
Класс BaseEntityEventListener предоставляет методы-обработчики различных событий сущности (табл. 1).
Табл. 1. — Методы-обработчики событий сущности
OnDeleted(object sender, EntityAfterEventArgs e) |
Обработчик события после удаления записи. |
OnDeleting(object sender, EntityBeforeEventArgs e) |
Обработчик события перед удалением записи. |
OnInserted(object sender, EntityAfterEventArgs e) |
Обработчик события после добавления записи. |
OnInserting(object sender, EntityBeforeEventArgs e) |
Обработчик события перед добавлением записи. |
OnSaved(object sender, EntityAfterEventArgs e) |
Обработчик события после сохранения записи. |
OnSaving(object sender, EntityBeforeEventArgs e) |
Обработчик события перед сохранением записи. |
OnUpdated(object sender, EntityAfterEventArgs e) |
Обработчик события после обновления записи. |
OnUpdating(object sender, EntityBeforeEventArgs e) |
Обработчик события перед обновлением записи. |
Параметры методов:
- sender — ссылка на экземпляр сущности, генерирующий событие. Тип параметра — Object.
- e — аргументы события. В зависимости от момента выполнения метода-обработчика (после или до события), тип аргумента может быть или EntityAfterEventArgs, или EntityBeforeEventArgs.
Последовательность вызова методов-обработчиков событий приведена в таблице 2.
Таблица 2. — Последовательность вызова методов-обработчиков
Создание | Изменение | Удаление |
---|---|---|
OnSaving() OnInserting() OnInserted() OnSaved() |
OnSaving() OnUpdating() OnUpdated() OnSaved() |
OnDeleting() OnDeleted() |
Получение экземпляра UserConnection
Экземпляр UserConnection в обработчиках событий необходимо получать из параметра sender:
[EntityEventListener(SchemaName = "Activity")] public class ActivityEntityEventListener : BaseEntityEventListener { public override void OnSaved(object sender, EntityAfterEventArgs e) { base.OnSaved(sender, e); var entity = (Entity) sender; var userConnection = entity.UserConnection; } }
Подход получения UserConnection из HttpContext не всегда верный. Например, при срабатывании обработчиков событий в бизнес-процессах или в планировщике задач экземпляр HttpContext отсутствует.
Класс EntityAfterEventArgs
Класс предоставляет свойства с аргументами метода-обработчика, выполняемого после возникновения события:
- ModifiedColumnValues — коллекция измененных колонок.
- PrimaryColumnValue — идентификатор записи.
Класс EntityBeforeEventArgs
Класс предоставляет свойства с аргументами метода-обработчика, выполняемого до возникновения события:
- KeyValue — идентификатор записи.
- IsCanceled — позволяет отменить дальнейшее выполнение события.
- AdditionalCondition — позволяет дополнительно описать условия фильтрации сущности перед действием.
Атрибут EntityEventListener
Атрибут EntityEventListener (класс EntityEventListenerAttribute) предназначен для регистрации слушателя. Слушатель может быть связан со всеми объектами (IsGlobal = true) или с конкретным объектом (например, SchemaName = “Contact”). Один класс-слушатель можно помечать множеством атрибутов для определения необходимого набора “прослушиваемых” сущностей.
Асинхронные операции в событийном слое Entity
Зачастую дополнительная бизнес-логика на объекте продолжительна во времени и выполняется последовательно. Подобный подход негативно сказывается на производительности клиентской части, например, при сохранении или изменении сущности.
Для устранения подобных проблем был разработан механизм асинхронного выполнения операций, основанный на событийном слое Entity.
Например, при создании новой активности необходимо выполнить дополнительную логику, которая в принципе может выполняться асинхронно. Для этого необходимо создать класс, например, DoSomethingActivityAsyncOperation с реализацией интерфейса IEntityEventAsyncOperation (см. ниже).
//Класс, реализующий асинхронный вызов операций. public class DoSomethingActivityAsyncOperation: IEntityEventAsyncOperation { // Стартовый метод класса. public void Execute(UserConnection userConnection, EntityEventAsyncOperationArgs arguments) { // ... } }
В классе-слушателе объекта активности, в методе-обработчике после сохранения записи при помощи фабрики классов нужно получить экземпляр, реализующий интерфейс IEntityEventAsyncExecutor, подготовить параметры и передать класс операции DoSomethingActivityAsyncOperation на выполнение.
[EntityEventListener(SchemaName = "Activity")] public class ActivityEntityEventListener : BaseEntityEventListener { // Метод-обработчик события после сохранения сущности. public override void OnSaved(object sender, EntityAfterEventArgs e) { base.OnSaved(sender, e); // Экземпляр класса для асинхронного выполнения. var asyncExecutor = ClassFactory.Get<IEntityEventAsyncExecutor>(); // Параметры для асинхронного выполнения. var operationArgs = new EntityEventAsyncOperationArgs((Entity)sender, e); // Выполнение в асинхронном режиме. asyncExecutor.ExecuteAsync<DoSomethingActivityAsyncOperation>(operationArgs); } }
Интерфейс IEntityEventAsyncExecutor
Предоставляет метод для асинхронного выполнения операций.
- void ExecuteAsync<TOperation>(object parameters) — типизированный метод для запуска операции с параметрами, где TOperation — конфигурационный класс, реализующий интерфейс IEntityEventAsyncOperation.
Интерфейс IEntityEventAsyncOperation
Предоставляет метод для запуска асинхронной операции.
- void Execute(UserConnection userConnection, EntityEventAsyncOperationArgs arguments) — метод для запуска.
В классе, реализующем интерфейс IEntityEventAsyncOperation, нежелательно описывать логику изменения основной сущности. Подобное использование может привести к неверному формированию данных. Также не стоит выполнять легковесные операции (например, подсчет значения поля), т. к. создание отдельного потока может занимать больше времени, чем выполнение самой операции.
Класс EntityEventAsyncOperationArgs
Экземпляры этого класса используются в качестве аргумента для передачи в асинхронную операцию.
Свойства:
- EntityId — идентификатор записи.
- EntitySchemaName — название схемы.
- EntityColumnValues — словарь текущих значений колонок сущности.
- OldEntityColumnValues — словарь старых значений колонок сущности.