CQRS+DDD命令端查询其他聚合根的id

CQRS+DDD command side query for other aggregate root by id

鉴于以下 CQRS + DDD 背景:


聚合根:

class Message{Guid guid, string content, Guid toUserGuid, MessageStatus status...}

class User{Guid guid, string name, Email email...}


命令:

CreateMessageCommand{Guid messageGuid, string content, Guid toUserGuid...}


命令处理程序:

CreateMessageCommandHandler<CreateMessageCommand> => 创建一个消息聚合根(状态设置为例如“Request Received”)并通过MessageRepository保存(消息尚未发送。CreateMessageCommandHandler仅创建和保存消息聚合根)。然后发布一个MessageCreatedEvent


事件:

MessageCreatedEvent{Guid messageGuid}


事件处理程序:

MessageCreatedEventHandler<MessageCreatedEvent> => 使用 event.messageGuid 通过 MessageRepository 获取 Message => ??? => emailService.Send(user.email, message.content) => 状态设置为“已发送”


我的问题是,在MessageCreatedEventHandler<MessageCreatedEvent>“???”部分,我是否可以使用 message.toUserGuid 通过 UserRepository 获得 User,例如得到 user.email。另一种选择是使用方法 GetEmailById(Guid userGuid) => Email 的域服务 UserService,我认为这更好,因为事件处理程序不需要 User 的整个对象,并且 UserService 可以处理如何检索 User 的所有逻辑(例如 UserRepository

我不想在这里获取读取模型(查询端),我只需要来自聚合根的一些信息,这不是当前上下文。

谢谢,非常感谢与此主题相关的任何评论和回答。

TLDR:在 CQRS 命令 handler/event 处理程序中,我应该如何获取有关当前 command/event 上下文之外的聚合根的信息。

TLDR: In CQRS command handler/event handler, how should I get information about aggregate root which is outside my current command/event context.

通常的回答:你向一些商店索取你需要的信息的解锁副本。该信息是 data on the outside,这意味着权威副本可能会在您工作时发生变化(例如:您的用户在您尝试发送消息时更改了他们的电子邮件地址)。

从机制上讲,这通常看起来像是有一些接受标识符和 returns 您需要的信息的“服务”(想想“存储库”,但没有更改数据的能力)。

根据上下文,您可以从您的“应用程序代码”调用该服务,并将答案传递给您的“领域代码”,或者您可以将服务本身传递给领域代码(这是领域服务模式).

在任何一种情况下,让机器做正确的事情都是相对直接的;选择主要是设计权衡之一(例如:从远程源复制数据可能会失败 - 您是否希望错误处理与您的域代码混合?)