Ncqrs: как вызвать событие без наличия совокупного корня

#domain-driven-design #cqrs #ncqrs

#domain-driven-design #cqrs #ncqrs

Вопрос:

Учитывая, что у меня есть два ограниченных контекста:

  1. Fleet Mgt — простой вспомогательный поддомен на основе CRUD
  2. Продажи — это мой основной домен на основе 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 { ... });