#domain-driven-design #cqrs #ncqrs
#domain-driven-design #cqrs #ncqrs
Вопрос:
Учитывая, что у меня есть два ограниченных контекста:
- Fleet Mgt — простой вспомогательный поддомен на основе CRUD
- Продажи — это мой основной домен на основе CQRS
Когда в управлении автопарком происходит операция CRUD, должно быть опубликовано событие, отражающее операцию:
- AircraftCreated
- AircraftUpdated
- AircraftDeleted
- и т.д.
Эти события требуются а) для обновления различных индексных таблиц, которые необходимы в домене продаж, и б) для обеспечения единого журнала аудита.
Вопрос: Есть ли простой способ сохранить и опубликовать эти события (для InProcessEventBus
, я здесь не использую NSB), не проходя через AggregateRoot
, что мне не понадобилось бы в простом контексте CRUD.
Ответ №1:
Если вы хотите опубликовать событие о чем-то, это что-то, вероятно, является совокупным корнем, потому что это внешне идентифицированный объект в интересующем пакете, иначе зачем вам отслеживать их?
Имея это в виду, вам не нужны индексные таблицы (я понимаю, что они предназначены для запросов) в отделе продаж BC. Вам нужны GUID самолета и только поиск / объединение на стороне чтения.
Для аудита я бы просто добавил общее событие аудита через отражение в репозиториях / единицах работы.
Ответ №2:
По словам Питера, основного участника Ncqrs, нет способа сделать это из коробки.
В этом сценарии я не хочу проходить всю церемонию создания и выполнения команды, а затем загружать совокупный корень из хранилища событий только для того, чтобы он выдал событие.
Поведение — это простой CRUD, реализованный с использованием самого простого возможного решения, которое в данном конкретном случае представляет собой формы поверх данных с использованием Entity Framework. Единственное, что мне нужно, это событие, публикуемое после совершения транзакции.
Мое решение выглядит так:
// Abstract base class that provides a Unit Of Work
public abstract class EventPublisherMappedByConvention
: AggregateRootMappedByConvention
{
public void Raise(ISourcedEvent e)
{
var context = NcqrsEnvironment.Get<IUnitOfWorkFactory>()
.CreateUnitOfWork(e.EventIdentifier);
ApplyEvent(e);
context.Accept();
}
}
// Concrete implementation for my specific domain
// Note: The events only reflect the CRUD that's happened.
// The methods themselves can stay empty, state has been persisted through
// other means anyway.
public class FleetManagementEventSource : EventPublisherMappedByConvention
{
protected void OnAircraftTypeCreated(AircraftTypeCreated e) { }
protected void OnAircraftTypeUpdated(AircraftTypeUpdated e) { }
// ...
}
// This can be called from anywhere in my application, once the
// EF-based transaction has succeeded:
new FleetManagementEventSource().Raise(new AircraftTypeUpdated { ... });