23

在我们的应用程序中,当域模型发生变化时,我们会引发域事件。事件处理程序执行的某些任务必须在引发事件时使用的同一事务中完成,其他任务必须在此事务之外执行。

例如,

当 Orderline 添加到 Order 实体时,会引发 OrderLineAdded 域事件,一个域事件会更改域模型的状态(因此必须在同一事务中执行),然后当事务完成时,必须更新 UI。

你会如何处理这个问题?

  1. 引发两个事件,一个在事务内部,一个在事务外部。
  2. 在事务内部引发事件,但使用事件处理程序发送异步请求以更新 UI?

选项 1 似乎令人困惑,因为事件名称必须以某种方式传达它们是在事务中还是在事务之外,但是对于选项 2,域事件的处理程序必须始终假定它们是从事务中同步调用的。

也许有更好的方法?

4

2 回答 2

21

我有一个类似的问题。领域模型正在发布事件(使用 Udi Dahan在此处描述的技术)。然后我意识到即使出现问题并且稍后回滚事务,也会调用与 UI 相关的处理程序。

为了解决这个问题,我向系统引入了另一个角色,另一种事件处理程序。我有ITransactionalEventHadnelerINonTransactionalEventHandler。前者在方法中立即被同步调用DomainEvents.Publish()。后者排队等待事务提交后立即调用(使用 System.Transactions 挂钩)。该解决方案运行良好,可读性和可维护性都很好。

于 2011-01-17T12:33:14.493 回答
1

我认为这两种方法都不错,只需在代码的每个部分都坚持相同的方法:

  1. 您将需要两个(或更多)事件处理程序,一个用于事务范围内的域模型的上下文,另一个用于辅助上下文,如 UI。你的域代码不应该关心代码的其他部分做什么,只需通知他们域数据的变化。
  2. 您的域代码事件处理程序方法可能会将异步事件发送到 UI 或其他模块。域事件应该是同步的,否则您需要两阶段提交来保持事务性。

我个人更喜欢选项 2,因为它使域代码更干净,并且通过使用异步通信,核心和其他模块将解耦,因此外部模块中的问题不会阻碍核心的工作。另一方面,在某些情况下,选项 1 可能更有利。

于 2011-01-16T21:38:10.070 回答