我用这个Checkout方法创建了一个基本的ShoppingCartService:
public void Checkout(IEnumerable<ShoppingCartItem> cart,Customer customer) { var order = new Order(cart,customer); _orderRepositorty.Add(order); _unitOfWork.Commit(); }
在此示例中,Order的构造函数将引发OrderCreated事件,该事件可由某些处理程序处理.但是,我不希望在实体尚未持久化或持久化以某种方式失败时引发这些事件.
1.提升服务中的事件:
我可以在服务中引发事件,而不是在域对象中引发事件.在这种情况下,Checkout方法将引发OrderCreated事件.这种方法的一个缺点是,通过查看Order域对象,不清楚哪些事件是由哪些方法引发的.此外,开发人员必须记住在其他地方创建订单时提出事件.感觉不对劲.
2.队列域事件
另一个选项是对域事件进行排队,并在保持成功时引发它们.这可以通过using语句来实现,例如:
using (DomainEvents.QueueEvents<OrderCreated>()) { var order = new Order(cart,customer); _orderRepositorty.Add(order); _unitOfWork.Commit(); }
QueueEvents< T>方法将布尔值设置为true,并将DomainEvents.Raise< T>设置为method会对事件进行排队,而不是直接执行它.在QueueEvent< T>的dispose回调中,执行排队事件以确保已经发生持久化.这似乎相当棘手,它需要服务知道域对象中引发了哪个事件.在我提供的示例中,它也只支持一种类型的事件,但是,这可以解决.
3.坚持域名活动
我可以使用域事件来持久化对象.这似乎没问题,除了持久化对象的事件处理程序应首先执行这一事实,但我在某处读到域事件不应该依赖于特定的执行顺序.也许这不是那么重要,域事件可能以某种方式知道处理程序应该执行的顺序.例如:假设我有一个定义域事件处理程序的接口,实现将如下所示:
public class NotifyCustomer : IDomainEventHandler<OrderCreated> { public void Handle(OrderCreated args) { // ... } }
当我想处理持久使用事件处理程序时,我会创建另一个处理程序,派生自同一个接口:
public class PersistOrder : IDomainEventHandler<OrderCreated> { public void Handle(OrderCreated args) { // ... } } }
现在NotifyCustomer行为取决于数据库中保存的顺序,因此PersistOrder事件处理程序应首先执行.是否可以接受这些处理程序引入一个属性,例如表明它们执行的顺序?快速执行DomainEvents.Raise< OrderCreated>()方法:
foreach (var handler in Container.ResolveAll<IDomainEventHandler<OrderCreated>>().OrderBy(h => h.Order)) { handler.Handle(args); }
现在我的问题是,我还有其他选择吗?我错过了什么吗?您如何看待我提出的解决方案?
解决方法
您可能还会发现这些问题和答案很有用:
CQRS: Storing events and publishing them – how do I do this in a safe way?
Event Aggregator Error Handling With Rollback
第3点更新:
… however I read somewhere that domain events should not rely on a specific order of execution.
无论你的坚持方式如何,事件的顺序绝对重要(在一个集合内).
Now NotifyCustomer behavIoUr depends on the order being saved in the database,so the PersistOrder event handler should execute first. Is it acceptable that these handlers introduce a property for example that indicates the order of their execution?
持久化和处理事件是一个单独的问题 – 不要使用事件处理程序持久化.首先坚持,然后处理.