I am implementing an application with domain driven design and event sourcing. I am storing all domain events in a DomainEvents table in SQL Server.
I have the following aggregates:
- City
+ Id
+ Enable()
+ Disable()
- Company
+ Id
+ CityId
+ Enable()
+ Disable()
- Employee
+ Id
+ CompnayId
+ Enable()
+ Disable()
Each one encapsulates its own domain logic and invariants. I designed them as separate aggregates, because one city may have thousands (maybe more) companies and company may also have very large number of employees. If this entities would belong to the same aggregate I had to load them together, which in most cases would be unnecessary.
Calling Enable or Disable will produce a domain event (e.g. CityEnabled
, CompanyDisabled
or EmployeeEnabled
). These events contain the primary key of the enabled or disabled entity.
Now my problem is a new requirement forcing me to enable/disable all related Companies if a City is enabled/disabled. The same is required for Employees, if a Company is enabled/disabled.
In my event handler, which is invoked if for example CityDisabled
has occurred
I need to execute DisableCompanyCommand
for each company belonging to that city.
But how would I know what companies should be affected by that change?
My thoughts:
Querying the event store is not possible, because I can't use conditions like 'where CityId = event.CityId'
Letting the parent know its child ids and putting all child ids in every event the parent produces. Is also a bad idea because the event creator shouldn't care who will consume the events later. So only information belonging to the happening event should be in the event.
Executing the DisableCompanyCommand
for every company. Only the companies having the matching CityId
would change their state. Even though I would do that asynchronously it would produce a huge overhead loading every company on those events. And also for every company getting disabled the same procedure should be repeated to disable all users.
Creating read models mapping ParentIds to ChildIds and loading the childIds according to the parentId in the event. This sounds like the most appropriate solution, but the problem is, how would I know if a new Company is created while I am disabling the existing ones?
I am not satisfied with any of the solutions above. Basically the problem is to determine the affected aggregates for a happened event.
Maybe you have better solutions ?
What you are describing can be resolved by a Saga/Process manager that listen to the CityDisabled
event. Then it finds the CompanyIds
of all Companies
in that City
(by using an existing Read model
or by maintaining a private state of CityIds
xCompanyIds
) and sends each one a DisableCompany
command.
The same applies to CompanyDisabled
event, regarding the disabling of Employee
.
P.S. Disabling a City/Company/Employee seems like CRUD to me, these don't seem terms from a normal ubiquitous language, it's not very DDD-ish but I consider your design as being correct in regard to this question.