Order
对象可能有像OrderStatusChanged
或NoteCreatedForOrder
这样的事件。在大多数情况下,这些事件会导致发送电子邮件,因此我不能只把它们留在MVC应用程序中。我已经阅读了Udi Dahan的Domain Events以及其他许多关于如何做这种事情的想法,并决定使用基于NServiceBus的主机来处理事件消息。我已经进行了一些概念验证测试,这似乎很有效。
我的问题是实际上应该在哪个应用程序层次上引发事件。我不想在相关对象成功持久化之前触发事件(如果持久性失败,则无法发送有关创建笔记的电子邮件)。
另一个问题是,在某些情况下,事件与聚合根以下的对象绑定。在上面的例子中,通过将其添加到
Order.Notes
集合并保存订单来保存Note
。这会带来一个问题,即当保存Order
时,难以评估应该触发哪些事件。我想避免在保存更新后的副本之前拉取当前对象的副本并查找差异。
UI是否适合触发这些事件?它知道发生了哪些事件,并且可以只在服务层成功保存对象后才触发它们。让控制器触发域事件似乎有些不妥。
存储库是否应在成功持久化后触发事件?
我应该将事件分开,让存储库存储一个
Event
对象,然后由轮询服务接收该对象,然后将其转换为NServiceBus事件(或直接从轮询服务处理)吗?
有没有更好的方法来处理这个问题?也许可以让我的领域对象排队等待事件,只有在对象被持久化后才由服务层触发事件?
更新:我有一个服务层,但是它似乎很繁琐和多余,需要通过比较过程确定在保存给定聚合根时应该触发哪些事件。因为其中一些事件是粒度细的(例如“订单状态已更改”),所以我认为必须检索对象的数据库副本,比较属性以创建事件,保存新对象,然后在保存操作成功完成后将事件发送到 NServiceBus。
更新
我最终做的事情是,在我下面发布的答案之后(way below),将一个名为 EventQueue
的 List<IDomainEvent>
属性构建到我的领域实体中。然后,根据领域的需要添加事件,这样我就可以保持逻辑处于领域内部,我认为这是合适的,因为我是基于实体内部正在发生的事情触发事件。
然后,在我的服务层中持久化对象时,我处理该队列并实际将事件发送到服务总线。最初,我打算使用一个使用标识 PK 的旧数据库,因此我必须后处理这些事件以填充实体的 ID,但我最终决定切换到 Guid.Comb
PK,这使我可以跳过该步骤。