CQRS где ответственность за чтение, и ответственность за записи, которые разделены на на отдельные части:
- Написать магазин, хранилище событий сохраняться все события, которые происходят в вашем домене
- Прочтите хранилище, чтобы сохранить прогнозы, которые инкрементно создаются из потока событий, поступающих из хранилища событий модели записи.
Вы получили это правильно, в том, что ваш RenameDepartmentCommandHandler
будет обрабатывать команду RenameDepartmentCommand
:
public void RenameDepartmentCommandHandler(RenameDepartmentCommand command)
{
// repository is injected in for us during command handler instantiation
var dept = this.repository.GetByDeptName(command.DepartmentName);
dept.RenameDepartment(command.NewDepartmentName);
this.repository.Save(dept);
// the repository will save all of the events, once committed
// a separate piece of code running in the background will
// listen for new events from the the event-store and dispatch
// them to anyone who may be listening
}
Фактическое предприятие должно было бы быть обновлены в модели записи на сохраняющиеся событие, это ваш единственный источник истины. Вы бы не только обновили модель чтения, вы всегда обновляете модель записи.
После того, как модель записи сохранила это событие, она будет отправлена (в некоторый момент времени в будущем) на считываемую модель.
Модель чтения является подчиненным от модели записи. Поскольку он является подчиненным, он будет в конечном итоге последовательным (для моделей чтения и записи, которые используют отдельную инфраструктуру и которые не используют распределенные транзакции) ... в конечном итоге последовательная не означает проблему, обычно задержка (от 10 мс до секунды или даже минут) является приемлемым для большинства проблемных пространств.
Таким образом, ваш объект будет выглядеть следующим образом:
public class Department : AggregateBase
{
// this class derives from jOliver's CommonDomain project
// only useful if using C# - there will be similar
// event sourcing infrastructure projects for different
// languages
public string Name { get; protected set; }
// all other properties go here
public void RenameDepartment(public newName)
{
// the DepartmentRenamed is an immutable class taking the
// current name and new name as constructor parameters
RaiseEvent(new DepartmentRenamed(this.Name, newName));
}
protected void Apply(DepartmentRenamed evnt)
{
this.Name = event.NewName;
}
}
И ваша проекция модель чтения что-то вроде этого:
public class DeptNameListProjection : IEventHandler<DepartmentRenamed>
{
public void Handle(DepartmentRenamed evntFromEventStore)
{
var department = this.readStore.Find(evntFromEventStore.OldName);
// write it, depends on your infrastructure
// normally a SqlCommand or similar is fine here, I try and avoid
// using an ORM as imho flat tables make more sense for read models
}
}
Спасибо Thats очень полезным :-) – Matt