I often have to deal with similar situation (but please note I’m on 2.6) and I often find out the reason is to have a “traditional” design - sequential and synchronous - that is not very well suited to DDD modeling. In your case instead of
Aggregate - EntityAggregate
Command - CreateEntityCommand
Event - NewEntityCreatedEvent
Saga - FulfillmentProcessSaga
Aggregate Creates Data → Publishes Event → Saga Gets the Event → Queries Data
What I would do is
Aggregate - EntityAggregate
Command - StartCreateEntityCommand, FinishCreateEntityCommand
Event - NewEntityCreationStartedEvent, NewEntityCreatioFinishedEvent
Saga - FulfillmentProcessSaga
Aggregate receives StartCreateEntityCommand (updates it’s internal state only) → Publishes NewEntityCreationStartedEvent → Saga Gets the NewEntityCreationStartedEvent → Saga Creates Data → Sends FinishCreateEntityCommand
Aggregate receives FinishCreateEntityCommand (updates it’s internal state only) → Publishes NewEntityCreatioFinishedEvent-> Saga Gets the NewEntityCreatioFinishedEvent-> Saga Queries Data
I stress what Steven said that is in fact very important:
From your response I get the feeling that you’re storing data in a database in a command handling function on an aggregate. If that’s the case, I highly suggest not doing that, as it’s mixing the Command and the Query side of your application
A command handler should perform business logic based on state your aggregate contains and make the decision whether an event should happen yes/no.
It is thus not in charge of updating views, it just makes a decision of a certain action is valid or not. The event in that sense notifies everybody that that decision has been made.
After that, an event handling component in the query side of your application will handle that event.
In most cases such an event handling component will create/update a projections/view, but it might also perform certain other actions like sending an email or in the case of sagas publish another command.
And I actually would go a step further to say that Aggregates, besides raising events based on the business decisions, should do nothing except taking care of it’s internal state - specially they should do nothing that affects “the external world”. All those things - writing to models, iterating with other systems, etc… - should be done either by simple listeners or sagas if they are complex, long lived transaction that need to keep their own internal state, and that in turn should send commands to notify the aggregate if needed.
Much more verbose but that’s the price to pay to have asynchronous processing and all the DDD/Event driven/CQRS styles of processing.