IEntityTypeCustomHooks<TEntity> — интерфейс для реализации пользовательской логики обработки операций над сущностью.
Реализация интерфейса позволяет перехватывать ключевые этапы работы с сущностью:
Методы интерфейса система вызывает автоматически в нужные моменты выполнения операции.
Обработчики расширяют стандартную логику платформы.
Типичные сценарии использования:
public interface IEntityTypeCustomHooks<in TEntity>
where TEntity : class, IEntity
{
// CRUD операции
Task BeforeUpsert(CustomHooksContext context, TEntity detachedEntity);
Task BeforeDelete(CustomHooksContext context, TEntity detachedEntity);
Task AfterUpsert(CustomHooksContext context, TEntity contextEntity, TEntity detachedEntity);
Task AfterDelete(CustomHooksContext context, TEntity contextEntity);
// Жизненный цикл
Task BeforeSetState(CustomHooksContext context, TEntity entity, Guid oldStateId, Guid newStateId);
Task AfterSetState(CustomHooksContext context, TEntity entity, Guid oldStateId, Guid newStateId);
// Workflow
Task BeforeStartWorkflow(CustomHooksContext context, TEntity contextEntity);
}
Эти методы вызываются при выполнении CRUD-операций через сервис сущностей.
| Метод | Когда вызывается | Назначение |
|---|---|---|
| BeforeUpsert | До вставки или обновления сущности | Проверки, изменение данных перед сохранением |
| AfterUpsert | После вставки или обновления | Бизнес-логика, интеграции |
| BeforeDelete | До удаления сущности | Проверка возможности удаления |
| AfterDelete | После удаления | Очистка связанных данных, интеграции |
Task BeforeUpsert(CustomHooksContext context, TEntity detachedEntity);
Вызывается до сохранения сущности. Метод срабатывает для операций Insert и Update.
Параметры:
context — контекст выполнения обработчика;detachedEntity — сущность, переданная пользователем (не привязана к DbContext).Типичные сценарии:
Task AfterUpsert(CustomHooksContext context, TEntity contextEntity, TEntity detachedEntity);
Вызывается после сохранения сущности.
Параметры:
context — контекст выполнения обработчика;contextEntity — сущность из текущего DbContext;detachedEntity — исходная сущность из запроса.Типичные сценарии:
Task BeforeDelete(CustomHooksContext context, TEntity detachedEntity);
Вызывается перед удалением сущности.
Параметры:
context — контекст выполнения;detachedEntity — сущность, переданная для удаления.Типичные сценарии:
Task AfterDelete(CustomHooksContext context, TEntity contextEntity);
Вызывается после удаления сущности.
Параметры:
context — контекст выполнения;contextEntity — удалённая сущность.Типичные сценарии:
Методы вызываются при изменении состояния сущности, поддерживающей жизненный цикл (IStatedEntity).
| Метод | Когда вызывается |
|---|---|
| BeforeSetState | До изменения состояния |
| AfterSetState | После изменения состояния |
Task BeforeSetState(
CustomHooksContext context,
TEntity entity,
Guid oldStateId,
Guid newStateId
);
Вызывается перед изменением состояния.
Параметры:
entity — сущность, для которой выполняется переход;oldStateId — текущее состояние;newStateId — новое состояние.Типичные сценарии:
Task AfterSetState(
CustomHooksContext context,
TEntity entity,
Guid oldStateId,
Guid newStateId
);
Вызывается после изменения состояния.
Типичные сценарии:
Task BeforeStartWorkflow(CustomHooksContext context, TEntity contextEntity);
Вызывается перед запуском workflow для сущности.
Параметры:
context — контекст выполнения;contextEntity — сущность из текущего DbContext.Типичные сценарии:
CustomHooksContext — контекст выполнения динамического кода. Предоставляет доступ к API системы:
Сущность, полученная из запроса пользователя. Особенности:
DbContext;Сущность, загруженная из базы данных и отслеживаемая текущим DbContext. Используется для:
public class CustomHooks : IEntityTypeCustomHooks<Project>
{
public async Task BeforeUpsert(
CustomHooksContext context,
Project detachedEntity)
{
if (string.IsNullOrWhiteSpace(detachedEntity.Name))
await context.Log("Имя проекта не задано", DynamicCodeLogLevel.Error);
}
public async Task AfterUpsert(
CustomHooksContext context,
Project contextEntity,
Project detachedEntity)
{
await context.Log($"Проект сохранён: {contextEntity.Id}");
}
public async Task BeforeSetState(
CustomHooksContext context,
Project entity,
Guid oldStateId,
Guid newStateId)
{
await context.Log($"Смена состояния: {oldStateId} → {newStateId}");
}
public Task AfterDelete(CustomHooksContext context, Project entity)
=> Task.CompletedTask;
public Task BeforeDelete(CustomHooksContext context, Project entity)
=> Task.CompletedTask;
public Task AfterSetState(CustomHooksContext context, Project entity, Guid oldStateId, Guid newStateId)
=> Task.CompletedTask;
public Task BeforeStartWorkflow(CustomHooksContext context, Project entity)
=> Task.CompletedTask;
}
Методы интерфейса IEntityTypeCustomHooks<TEntity> вызываются системой в определённой последовательности в рамках операции над сущностью.
Все хуки выполняются в одной транзакции. Если в любом из них возникает исключение — операция отменяется и изменения не сохраняются.
При создании или обновлении сущности:
BeforeUpsert
↓
сохранение сущности
↓
AfterUpsert
↓
BeforeCommit
↓
commit транзакции
↓
AfterCommit
При удалении сущности:
BeforeDelete
↓
удаление сущности
↓
AfterDelete
↓
BeforeCommit
↓
commit транзакции
↓
AfterCommit
При изменении состояния жизненного цикла:
BeforeSetState
↓
смена состояния
↓
AfterSetState
↓
BeforeCommit
↓
commit транзакции
↓
AfterCommit
BeforeStartWorkflow
↓
запуск workflow
↓
BeforeCommit
↓
commit транзакции
↓
AfterCommit
AfterCommit выполняются внутри транзакции.AfterCommit выполняется после сохранения изменений.AfterCommit.Перейти на русскую версию?