域事件应该在事务内部还是外部引发?

时间:2011-01-14 13:50:41

标签: architecture domain-driven-design domain-events

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

例如,

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

你会如何解决这个问题?

  1. 提升两个事件,一个在事务内部,另一个在事务外部。
  2. 提升事务内部的事件,但是使用事件处理程序发送Async请求来更新UI?
  3. 选项1似乎令人困惑,因为事件名称必须以某种方式传达它们进出事务,但是使用选项2域事件的处理程序必须始终假定它们是从事务中同步调用的。

    也许有更好的方法?

2 个答案:

答案 0 :(得分:17)

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

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

答案 1 :(得分:1)

我认为这两种方法都可以很好,只需在代码的每个部分都坚持使用相同的方法:

  1. 您需要两个(或更多)事件处理程序,一个用于事务范围内的域模型的上下文,另一个用于辅助上下文的其他(如UI)。您的域代码不应该关心代码的其他部分,只需通知他们有关域数据的更改。
  2. 您的域代码事件处理程序方法可能会向UI或其他模块发送异步事件。域事件应该是同步的,否则你需要两阶段提交来保持事务性。
  3. 我个人更喜欢选项2,因为它使域代码更加清晰,并且通过使用异步通信,核心和其他模块将被解耦,因此外部模块中的问题不会妨碍核心的工作。另一方面,可能存在选项1更有利的情况。