使用域事件模式

时间:2011-04-21 19:40:56

标签: c# domain-driven-design

我一直试图在udi dahan所描述的新项目中实现这种模式。

我喜欢if的想法,但我还不确定它应该在什么情况下应用(对这个东西来说是新的......)。

例如,假设我有一个OnUserCreated事件。我希望其中一位处理程序向用户发送确认电子邮件。但是,如果事件被触发,电子邮件将被发送,然后提交事务时出错并且数据永远不会保存到数据库中。这种模式适用于这种情况吗?我读过人们说不,但是我过去做过的一些项目实际上是这样做的。或者这是我应该只用于加载和更新其他实体的东西......另一方面,我读到有人说操作所需的关联实体应该已经加载,所以我不应该从数据库加载它们事件

2 个答案:

答案 0 :(得分:7)

当然,这取决于您选择如何实施系统。

您可以在此处考虑多个选项:

<强> 1。两阶段提交 在进行两阶段提交时,基本上每个处理程序包含3个方法:一个用于准备,一个用于提交,一个用于回滚。

对于所有事件处理程序,首先调用Prepare。如果这些都没有报告问题,则调用所有处理程序的Commit()方法。如果其中任何一个报告问题 - 尽管Prepare()调用没有报告任何问题 - 那么对于其Commit()已经执行的所有处理程序,您调用它们的Rollback()方法。

<强> 2。内部和外部事件处理程序 另一种选择是分离事件处理程序。您可以发布一个事件,例如UserCreated,它由首先参与事务的事件处理程序处理。事件作为事务的一部分存储在DB中。然后,您可以拥有外部事件处理程序,它们只对已存储在数据库中的事件做出反应 - 例如您的电子邮件发件人。这些只能在提交初始事务后调用。

我确信您可以考虑更多方法来处理您的具体情况。

答案 1 :(得分:3)

使用域事件允许您在业务事务(创建用户)之外移动某些操作(发送电子邮件)。事件的发布与db事务在同一事务中登记,因此如果db事务失败,则不会发布事件。使用持久消息排队系统(msmq)可确保在事件发布时最终执行处理程序。

您的流程应如下所示:

Begin Transaction
    Receive Command
    Call Aggregate Method 
        Publish Events // will only be published if the transaction succedes
Commit Transaction

Begin Transaction
    Receive Event
    Send Email
End Transaction

作为旁注,尝试在没有“On”前缀的情况下命名事件,因为在句子中使用它们更容易。