1

我正在尝试理解Udi Dahan 说明的关于在特定情况下添加新域实体的域事件模式。

现在通常使用实体创建它们,然后通过存储库添加它们。我想我还会这样做吗?

我的例子是我们通常将资产添加到系统中。像这样:

 var asset= new Asset();
/*bunch of prop setting*/
 _assetRepository.Add(asset);

然而,资产创建是我们希望遵循某些流程的结果。因此,开发人员建议我们不再需要这样做,因为它可以由域事件处理:

var asset= new Asset();
   /*bunch of prop setting*/
asset.Create(location);

现在 create 方法将引发一个事件并由一个 create 事件处理程序处理,该事件处理程序基本上只是将其插入到 repo 中,并做一些其他的事情给创建位置的仓库经理发送电子邮件等。

然而,在资产上创建事件对我来说看起来非常活跃。然而,在领域中,人们谈论正在创建的新资产。所以我们不确定。

想法?

4

2 回答 2

2

我已经为这个问题苦苦挣扎了很长时间。但没有好的解决办法。我认为,

  • 域事件不应在其所属的聚合成功持久化之前发布或处理
  • 发布任何领域事件不是应用层的责任

到目前为止,我认为最好的方法是利用 AOP。我们可以在聚合中“触发”事件,但不是立即分派它们,而是将其保存在队列中,并在相应的事务成功后真正分派它。
我们可以定义一个自定义的@Transactional 拦截器来实现这一点,从而使应用服务不知道任何“事件发布”的概念。

于 2013-08-08T05:49:14.683 回答
2

created 域事件应该在Asset类的构造函数中引发,因为那是创建该特定实体的时间。在您当前的实现中,这将是错误的,因为 Asset 实体提供了无参数构造函数。相反,创建一个具有所有必需属性作为参数的构造函数,从而防止创建处于不一致状态的资产实体。它可能看起来像这样:

public class Asset
{
  public Asset(string prop1, decimal prop2) 
  {
    this.Prop1 = prop1;
    this.Prop2 = prop2;
    DomainEvents.Raise(new AssetCreated(prop1, prop2));
  }

  public string Id { get; private set; }
  public string Prop1 { get; private set; }
  public decimal Prop2 { get; private set; }
}

创建实体后,您仍然必须使用存储库来持久化实体。这可能是有问题的,因为处理程序AssetCreated无法引用其 ID,因为在收到通知时尚未分配它。如果使用事件溯源,则创建事件将显式存储在底层事件存储中。

于 2012-08-28T02:11:36.337 回答