域事件应该在事务内部还是外部引发?
在我们的应用程序中,当域模型中发生某些变化时,我们会引发域事件。事件处理程序执行的某些任务必须在引发事件时使用的同一事务内完成,其他任务必须在此事务之外执行。
例如,
当将 Orderline 添加到 Order 实体时,会引发 OrderLineAdded 域事件,一个域事件会更改域模型的状态(因此必须在同一事务中执行),然后当事务完成时,UI 必须被更新。
您将如何解决这个问题?
- 引发两个事件,一个在事务内部,一个在事务外部。
- 在事务内部引发事件,但使用事件处理程序发送异步请求来更新 UI?
选项 1 似乎令人困惑,因为事件名称必须以某种方式传达它们位于事务内或事务外,但使用选项 2 时,域事件处理程序必须始终假设它们是从事务内同步调用的。
也许有更好的方法?
In our application we raise domain events when something changes in the domain model. Some of the tasks that are performed by the event handlers must be done within the same transaction that was used when the event is raised, other tasks must be performed outside of this transaction.
For example,
When an Orderline is added to an Order entity, the OrderLineAdded domain event is raised, one domain event changes the state of the domain model (so must be performed in the same transaction), then when the transaction is completed the UI must be updated.
How would you approach this problem?
- Raise two events, one inside the transaction, and one outside of the transaction.
- Raise the event inside of the transaction, but use the event handler to send an Async request to update the UI?
Option 1 seems confusing, since the events names must somehow convey they are in or out of a transaction, but with option 2 handlers of the domain event must always assume that they are called synchronously from within a transaction.
Maybe there is a better approach?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我也遇到过类似的问题。域模型正在发布事件(使用 Udi Dahan 在此处描述的技术)。然后我意识到,即使出现问题并且事务稍后回滚,我的 UI 相关处理程序也会被调用。
为了解决这个问题,我向系统引入了另一个角色,即另一种事件处理程序。我有
ITransactionalEventHadneler
和INonTransactionalEventHandler
。前者在DomainEvents.Publish()
方法中立即同步调用。后者会在事务提交后立即排队等待调用(使用 System.Transactions 挂钩)。该解决方案运行良好,并且具有良好的可读性和可维护性。I've had a similar problem. Domain model was publishing events (using the technique Udi Dahan describes here). Then I realized that my UI-related handlers are invoked even if something goes wrong and transaction is rolled back later.
To fix this I introduced another role to the system, another kind of event handler. I has
ITransactionalEventHadneler
andINonTransactionalEventHandler
. The former were invoked synchonously immediately inDomainEvents.Publish()
method. The latter were queued to be invoked as soon as transaction gets committed (using System.Transactions hooks). The solution worked fine and was quite readable and maintainable.我认为这两种方法都很好,只需在代码的每个部分坚持相同的方法:
我个人更喜欢选项2,因为它使域代码保持干净,并且通过使用异步通信,核心和其他模块将解耦,因此外部模块的问题不会妨碍核心的工作。另一方面,在某些情况下,选项 1 可能更有利。
I think both approach could be good, just stick to the same approach in every part of your code:
I personally like option 2 more, because it keeps the domain code cleaner and by using asynchronous communication the core and other modules will be decoupled, therefore problems in the external modules will not hinder the workings of the core. On the other hand, there may be circumstances where option 1 is more advantageous.