我的 ASP.NET MVC3 / NHibernate 应用程序需要触发和处理与我的域对象相关的各种事件。例如,一个Order
对象可能有类似的事件OrderStatusChanged
or NoteCreatedForOrder
。在大多数情况下,这些事件会导致发送电子邮件,因此我不能将它们留在 MVC 应用程序中。
我读过 Udi Dahan 的领域事件 http://www.udidahan.com/2009/06/14/domain-events-salvation/以及关于如何做此类事情的许多其他想法,我决定使用基于 NServiceBus 的主机来处理事件消息。我已经做了一些概念验证测试,这似乎效果很好。
我的问题是哪个应用程序层应该实际引发事件。在成功保留相关对象之前,我不想触发事件(如果持久性失败,则无法发送创建注释的电子邮件)。
另一个问题是,在某些情况下,事件与聚合根下的对象相关联。在上面的例子中,一个Note
通过将其添加到来保存Order.Notes
收集并保存订单。这带来了一个问题,因为很难评估当某个事件发生时应该触发哪些事件。Order
已保存。我想避免在保存更新的副本之前提取对象的当前副本并查找差异。
-
UI 引发这些事件是否合适?它知道发生了什么事件,并且只有在服务层成功保存对象后才能触发它们。让控制器触发域事件似乎有些问题。
-
成功持久化后,存储库是否应该触发事件?
-
我应该将事件完全分开,让存储库存储一个Event
然后由轮询器服务拾取对象并then变成 NServiceBus 的事件(或直接从轮询器服务处理)?
-
有一个更好的方法吗?也许让我的域对象对仅在对象持久化后由服务层触发的事件进行排队?
-
Update:我有一个服务层,但让它通过比较过程来确定保存给定聚合根时应触发哪些事件似乎很麻烦且过多。因为其中一些事件是细粒度的(例如“订单状态已更改”),所以我想我必须检索对象的数据库副本,比较属性以创建事件,保存新对象,然后在以下情况下将事件发送到 NServiceBus:保存操作成功完成。
Update
在我在下面发布的答案之后,我最终做了什么(低于 https://stackoverflow.com/a/5912179/240439),是在我的域实体中构建一个EventQueue
财产是List<IDomainEvent>
。然后,我在域的更改值得时添加了事件,这使我能够将逻辑保留在域内,我认为这是合适的,因为我是根据实体内发生的情况触发事件。
然后,当我将对象保留在服务层中时,我会处理该队列并将事件实际发送到服务总线。最初,我计划使用使用身份 PK 的旧数据库,因此我必须对这些事件进行后处理以填充实体的 ID,但我最终决定切换到Guid.Comb
PK 这让我可以跳过这一步。
我的解决方案是在域层和服务层中引发事件。
您的域名:
public class Order
{
public void ChangeStatus(OrderStatus status)
{
// change status
this.Status = status;
DomainEvent.Raise(new OrderStatusChanged { OrderId = Id, Status = status });
}
public void AddNote(string note)
{
// add note
this.Notes.Add(note)
DomainEvent.Raise(new NoteCreatedForOrder { OrderId = Id, Note = note });
}
}
您的服务:
public class OrderService
{
public void SubmitOrder(int orderId, OrderStatus status, string note)
{
OrderStatusChanged orderStatusChanged = null;
NoteCreatedForOrder noteCreatedForOrder = null;
DomainEvent.Register<OrderStatusChanged>(x => orderStatusChanged = x);
DomainEvent.Register<NoteCreatedForOrder>(x => noteCreatedForOrder = x);
using (var uow = UnitOfWork.Start())
{
var order = orderRepository.Load(orderId);
order.ChangeStatus(status);
order.AddNote(note);
uow.Commit(); // commit to persist order
}
if (orderStatusChanged != null)
{
// something like this
serviceBus.Publish(orderStatusChanged);
}
if (noteCreatedForOrder!= null)
{
// something like this
serviceBus.Publish(noteCreatedForOrder);
}
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)