C# 使用域事件模式

C# 使用域事件模式,c#,domain-driven-design,C#,Domain Driven Design,我一直在尝试在udi dahan描述的一个新项目中实现这种模式 我喜欢if的想法,但我还不太确定它应该应用于什么情况(这是新的东西…) 例如,假设我创建了一个事件。我希望其中一个处理程序向用户发送确认电子邮件。但是,如果事件被触发,电子邮件被发送,然后提交事务时出错,数据永远不会保存到数据库中,该怎么办。该模式是否适用于这种情况?我看过有人说不,但我看过的一些项目实际上就是这样做的。或者这是我应该只用来加载和更新其他实体的东西……另一方面,我读到有人说操作所需的关联实体应该已经加载,所以我不应该

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

我喜欢if的想法,但我还不太确定它应该应用于什么情况(这是新的东西…)


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

使用域事件允许您移动某些操作(发送电子邮件)在业务事务之外(创建用户)。事件的发布登记在与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”前缀来命名事件,因为在句子中使用它们更容易

当然,这取决于您选择如何实现您的系统

<>你可以在这里考虑多种选择:

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

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

2。内部和外部事件处理程序 另一个选项是分离事件处理程序。您可以发布事件,例如UserCreated,该事件由首先参与事务的事件处理程序处理。事件作为事务的一部分存储在数据库中。然后,您可以使用外部事件处理程序,这些处理程序只对数据库中已存储的事件(例如您的电子邮件发件人)作出反应。只有在提交初始事务后才能调用这些

我相信你可以想出更多的方法来处理你的具体情况