我的 ASP.NET MVC3 / NHibernate 应用程序需要触发和处理与我的域对象相关的各种事件。例如,一个Order
对象可能有类似OrderStatusChanged
或的事件NoteCreatedForOrder
。在大多数情况下,这些事件会导致发送电子邮件,因此我不能只将它们留在 MVC 应用程序中。
我已经阅读了 Udi Dahan 的Domain Events和许多其他关于如何做这类事情的想法,我决定使用基于 NServiceBus 的主机来处理事件消息。我已经做了一些概念验证测试,这似乎运作良好。
我的问题是哪个应用程序层实际上应该引发事件。在成功持久化相关对象之前,我不想触发事件(如果持久化失败,则无法发送创建便笺的电子邮件)。
另一个问题是,在某些情况下,事件与聚合根下的对象相关联。在上面的示例中,Note
通过将 a 添加到Order.Notes
集合并保存订单来保存它。这带来了一个问题,因为很难评估Order
保存 an 时应该触发哪些事件。我想避免在保存更新的副本之前提取对象的当前副本并查找差异。
UI 是否适合引发这些事件?它知道发生了哪些事件,并且只有在服务层成功保存对象后才能触发它们。让控制器触发域事件似乎有些不对劲。
成功持久化后存储库是否应该触发事件?
我应该完全分离事件,让存储库存储一个
Event
对象,然后由轮询服务获取,然后变成 NServiceBus 的事件(或直接从轮询服务处理)?有一个更好的方法吗?也许只有在对象被持久化后才让我的域对象排队由服务层触发的事件?
更新:我有一个服务层,但是让它通过比较过程来确定在保存给定的聚合根时应该触发哪些事件似乎很麻烦和过度。因为其中一些事件是细粒度的(例如“订单状态已更改”),我想我必须检索对象的数据库副本,比较属性以创建事件,保存新对象,然后将事件发送到 NServiceBus保存操作成功完成。
更新
在我在下面发布的答案之后(在下面),我最终做的是在我的域实体中构建EventQueue
一个List<IDomainEvent>
. 然后,我添加了对域进行更改的事件,这使我能够将逻辑保留在域内,我认为这是合适的,因为我是根据实体内发生的事情触发事件。
然后,当我将对象持久保存在我的服务层中时,我会处理该队列并将事件实际发送到服务总线。最初,我计划使用使用身份 PK 的遗留数据库,因此我必须对这些事件进行后处理以填充实体的 ID,但我最终决定切换到Guid.Comb
允许我跳过该步骤的 PK。