【发布时间】:2010-05-25 16:07:35
【问题描述】:
我正在开发一个event-sourced CQRS 实现,在应用程序/域层中使用 DDD。我有一个看起来像这样的对象模型:
public class Person : AggregateRootBase
{
private Guid? _bookingId;
public Person(Identification identification)
{
Apply(new PersonCreatedEvent(identification));
}
public Booking CreateBooking() {
// Enforce Person invariants
var booking = new Booking();
Apply(new PersonBookedEvent(booking.Id));
return booking;
}
public void Release() {
// Enforce Person invariants
// Should we load the booking here from the aggregate repository?
// We need to ensure that booking is released as well.
var booking = BookingRepository.Load(_bookingId);
booking.Release();
Apply(new PersonReleasedEvent(_bookingId));
}
[EventHandler]
public void Handle(PersonBookedEvent @event) { _bookingId = @event.BookingId; }
[EventHandler]
public void Handle(PersonReleasedEvent @event) { _bookingId = null; }
}
public class Booking : AggregateRootBase
{
private DateTime _bookingDate;
private DateTime? _releaseDate;
public Booking()
{
//Enforce invariants
Apply(new BookingCreatedEvent());
}
public void Release()
{
//Enforce invariants
Apply(new BookingReleasedEvent());
}
[EventHandler]
public void Handle(BookingCreatedEvent @event) { _bookingDate = SystemTime.Now(); }
[EventHandler]
public void Handle(BookingReleasedEvent @event) { _releaseDate = SystemTime.Now(); }
// Some other business activities unrelated to a person
}
根据我目前对 DDD 的理解,Person 和 Booking 都是单独的聚合根,原因有两个:
- 有时业务组件会从数据库中单独提取 Booking 对象。 (即,已获释的人之前的预订因信息不正确而被修改)。
- 当 Booking 需要更新时,Person 和 Booking 之间不应存在锁定争用。
另一个业务要求是一个人一次不能多次进行预订。因此,我担心在读取端查询查询数据库,因为那里可能存在一些不一致(由于使用 CQRS 并具有最终一致的读取数据库)。
是否应该允许聚合根通过 id 查询事件源后备存储中的对象(根据需要延迟加载它们)?还有其他更有意义的实施途径吗?
【问题讨论】:
-
" public Person(Identification Identification) { Apply(new PersonCreatedEvent(identification)); }" 如果你从内存中构建对象会发生什么,你不是在创建一个新人,但你会正在发布一个新事件。我喜欢你定义事件处理程序的方式。因此,知道对象的状态只能在将命令应用于存储库时更改,也许您也应该添加命令处理程序,除非您要完全基于事件,恕我直言,这没有多大意义。
-
我不明白为什么您要处理您自己的存储库应该发布的事件? “BookingCreatedEvent”
标签: repository domain-driven-design cqrs