CQRS return 中的查询应该只查询数据还是还可以检查项目是否存在?

Should queries in CQRS return only data or can also check if an item exists?

这个问题涉及到 CQRS 和 DDD。

我想创建一个 post 评论。这是我的终点: /posts/{postId}/comments <-- Http POST

但首先我需要检查是否存在具有特定 ID 的 post。在每篇文章中,关于 CQRS 和 DDD 的每本书中,每个 class 查询的名称都以 Getxxxxx 开头,并且它是 returns 数据。我在任何地方都找不到检查项目是否存在和 returns true/false 的查询示例,为什么?我想知道我是否可以创建一个名为“PostExistsQuery”的查询。 因为整个互联网上都没有类似的例子。 :O 也许我做错了什么? :0

[HttpPost("/posts/{postId}/comments")]
public async Task<IActionResult> CreatePostComment(Guid postId, CreateCommentDTO commentDTO)
{
    if (await _mediator.Send(new PostExistsQuery(postId)) == false) // check if a post exists
    {
        return NotFound();
    }

    var commentCommand = new CreateCommentCommand(Guid.NewGuid(), postId, commentDTO.Author, commentDTO.Content);
    await _mediator.Send(commentCommand);

    return CreatedAtAction(nameof(GetCommentById), new { id = commentCommand.CommentId });
}

您正在将业务逻辑泄漏到 API 层中。 API 层(控制器)应该简单地准备一个命令并将其发送到命令处理程序,如果需要,可能会事先应用访问控制。

根据您的域模型,可能会发生以下情况之一:

  1. 命令处理程序尝试从存储库中检索 post,以便对其调用 AddComment。如果此时 post 为空,则抛出。

  2. 你从存储库中得到一个 post 并将其传递到评论工厂,如果为空,它将抛出。

  3. 您只需传入 Id 并使用域事件处理程序验证其存在。如果不存在,则抛出。

  4. 您的数据库提供商在尝试添加具有无效 post id 的评论时将抛出 FK 违规。

无论是哪种情况,您都可以在命令处理程序(或命令处理管道)中捕获并将 PostNotFoundException 抛回给 API,然后可以 return 在 BadRequest 中处理。

尝试阅读更多关于 Layers in DDD 的内容,尤其是关于领域和应用层的内容。我认为您错过了一些核心概念,因为您的示例显示您试图在 API.

中实现业务逻辑

在您的具体示例中,Domain 层负责检查您的聚合是否存在。您应该在命令处理程序中使用 Repository 模式(或类似模式)来获取聚合并在处理后保存它们。当找不到聚合时,存储库抛出异常。

P.S。 CQRS 模式完全是关于应用程序读写端的责任隔离,因此您不应在命令端使用read-model。