【问题标题】:Should queries in CQRS return only data or can also check if an item exists?CQRS 中的查询应该只返回数据还是也可以检查项目是否存在?
【发布时间】:2022-02-17 02:26:48
【问题描述】:

这个问题涉及 CQRS 和 DDD。

我想创建一个帖子评论。这是我的端点: /posts/{postId}/cmets

但首先我需要检查是否存在具有特定 ID 的帖子。在每篇文章中,每本关于 CQRS 和 DDD 的书籍中,每个查询的类名都以 Getxxxxx 开头,并返回数据。我在任何地方都没有找到检查项目是否存在并返回真/假的查询示例,为什么?我想知道是否可以创建一个名为“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 });
}

【问题讨论】:

    标签: c# domain-driven-design cqrs


    【解决方案1】:

    尝试阅读有关Layers in DDD 的更多信息,尤其是有关域和应用层的信息。我认为您错过了一些核心概念,因为您的示例显示您尝试在 API 中实现业务逻辑。

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

    附: CQRS 模式是关于应用程序读写端的责任隔离,因此您不应该在命令端使用 read-model。

    【讨论】:

    • 哦,这是个好主意!我将从我将使用 Single() 的存储库中的命令处理程序中获取我的聚合 - 谢谢!
    【解决方案2】:

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

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

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

    2. 您从存储库中获得一个帖子并将其传递到评论工厂,如果为 null,它将抛出。

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

    4. 当您的数据库提供商尝试添加带有无效帖子 ID 的评论时,它会引发 FK 违规。

    无论它是什么,您都可以在命令处理程序(或命令处理管道)中捕获并将 PostNotFoundException 返回给 API,然后 API 可以在 BadRequest 中返回。

    【讨论】:

    • 谢谢!!!!我将使用第一点,在存储库中我将使用 Entity Framework 中的方法 Single(),它会抛出异常,我的 api 将返回 BadRequest!!!!你很棒!!!!!!太感谢了!!!几乎开发,你很棒:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    • 2019-07-28
    • 2020-10-17
    • 2020-10-29
    • 2014-02-15
    • 1970-01-01
    相关资源
    最近更新 更多