16

假设BookAuthor是我模型中的聚合根。

在阅读模型中,我有一个表格AuthorsAndBooks,它是作者和书籍的列表,由Book.AuthorId

触发事件时BookAdded,我想接收Author数据以创建新AuthorsAndBooks行。

因为Book是聚合根,事件Author中不包含有关的信息。BookAdded而且我不能包含它,因为Authorroot 没有吸气剂(根据所有示例和有关 CQRS 和事件溯源的帖子的指南)。

通常我会在这个问题上收到两种类型的答案:

  1. 使用事件处理程序中所需的所有数据丰富您的域事件。但正如我所说,我不能为聚合根做到这一点。
  2. 使用来自 View Model 的可用数据。即从视图模型加载Author并使用它来构建AuthorsAndBooks行。

最后一个在并发方面存在一些问题。BookAdded在处理事件时,视图模型中的作者数据可能不可用。

你用什么方法来解决这个问题?谢谢你。

4

5 回答 5

3

作为一般建议,让事件处理程序是幂等的,并确保您可以处理乱序消息处理(通过重新排队或构建机制来填充缺失的数据)。另一方面,请质疑为什么作者和书是如此绝望的聚合根源。也许您应该在添加一本书时从作者那里复制(f* 是“添加一本书”,这是一个命令)。问题在于所有这些虚构的例子。下降到现实世界,我怀疑你的问题是否存在。

于 2011-02-20T17:18:15.820 回答
3

您的问题缺少一些上下文,例如导致此事件的用户场景是什么以及您从什么状态开始?如果您正在为此案例编写 BDD 测试,它们会是什么样子?了解这一点将有助于回答您的问题。

如何解决将书与作者关联的问题取决于领域。首先,我们假设您的域具有 Author 聚合和 Book 聚合是有意义的,例如,如果我正在编写图书馆系统,我怀疑我是否会有作者聚合,因为我不关心一个没有他/她的书的作者,我关心的是书。

至于缺少 getter,值得一提的是,聚合根没有 getter,因为偏爱告诉-不问的 OOP 风格。但是,您可以告诉一个 AR 做某事,然后在需要时将某事告诉另一个 AR。重要的部分是 AR 会告诉其他人关于它自己的信息,而不是在你它的地方编写代码然后传递它。

最后,我要问一下,为什么你加书的时候没有作者ID?那你怎么知道作者是谁?我假设您可以执行以下操作(我的代码假设您使用流畅的界面来创建 AR,但您可以替换工厂、构造函数,无论您使用什么):

CreateNew.Book()
  .ForAuthor(command.AuthorId)
  .WithContent(command.Content);

现在的情况可能是您正在添加一本书以及一位全新的作者。我要么将其作为两个单独的命令处理(这可能对您的域更有意义),要么按以下方式处理命令:

var author = CreateNew.Author()
  .WithName(command.AuthorName);

var book = CreateNew.Book()
  .ForAuthor(author.Id)
  .WithContent(command.Content);

也许问题是您在聚合根 ID 上没有吸气剂,我认为这不是必要的或常见的。但是,假设 Id 封装对您很重要,或者您的 BookAdded 事件需要比 Id 提供的更多关于作者的信息,那么您可以执行以下操作:

var author = CreateNew.Author()
  .WithName(command.AuthorName);
var book = author.AddBook(command.Content);

// Adds a new book belonging to this Author
public Book AddBook(BookContent content) {
  var book = CreateNew.Book()
    .ForAuthor(this.Id)
    .WithContent(command.Content);
}

在这里,我们告诉作者添加一本书,此时它会为这本书创建聚合根并将它的 Id 传递给这本书。然后我们可以有事件 BookAddedForAuthor 将有作者的 id。

最后一个有缺点,它创建了一个必须通过多个聚合根执行的命令。我会尽可能地弄清楚为什么第一个例子不适合你。

此外,我不能过分强调您正在寻找的实现是如何由您的特定域上下文决定的。

于 2011-02-27T20:53:07.280 回答
2

恕我直言,从作者/书籍事件中填充读取模型,使用重新排序来处理事件乱序的情况(视图处理程序在它自己的一致性边界内,无论如何都应该处理排序/重复数据删除情况)。

于 2011-02-19T19:10:00.857 回答
0

The first thing I would ask is why there are concurrency issues in the read model. If the client is sending a reference to the author aggregate inside the AddBook command, where did it get the information from? If the book and author are created at the same time, then your event can probably be enriched. Let me know if I'm missing something here.

于 2011-02-18T23:36:32.520 回答
0

最后一个在并发方面存在一些问题。在处理 BookAdded 事件时,视图模型中的作者数据可能不可用。

“稍后处理事件”呢?因此,您只需将其放在队列的后面,直到该数据可用(可能有 x 次尝试和每次尝试之间 x 时间的限制)。

于 2011-02-19T18:53:05.057 回答