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 层(控制器)应该简单地准备一个命令并将其发送到命令处理程序,如果需要,可能会事先应用访问控制。
根据您的域模型,可能会发生以下情况之一:
命令处理程序尝试从存储库中检索 post,以便对其调用 AddComment。如果此时 post 为空,则抛出。
你从存储库中得到一个 post 并将其传递到评论工厂,如果为空,它将抛出。
您只需传入 Id 并使用域事件处理程序验证其存在。如果不存在,则抛出。
您的数据库提供商在尝试添加具有无效 post id 的评论时将抛出 FK 违规。
无论是哪种情况,您都可以在命令处理程序(或命令处理管道)中捕获并将 PostNotFoundException 抛回给 API,然后可以 return 在 BadRequest 中处理。
尝试阅读更多关于 Layers in DDD 的内容,尤其是关于领域和应用层的内容。我认为您错过了一些核心概念,因为您的示例显示您试图在 API.
中实现业务逻辑
在您的具体示例中,Domain 层负责检查您的聚合是否存在。您应该在命令处理程序中使用 Repository 模式(或类似模式)来获取聚合并在处理后保存它们。当找不到聚合时,存储库抛出异常。
P.S。 CQRS 模式完全是关于应用程序读写端的责任隔离,因此您不应在命令端使用read-model。
这个问题涉及到 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 层(控制器)应该简单地准备一个命令并将其发送到命令处理程序,如果需要,可能会事先应用访问控制。
根据您的域模型,可能会发生以下情况之一:
命令处理程序尝试从存储库中检索 post,以便对其调用 AddComment。如果此时 post 为空,则抛出。
你从存储库中得到一个 post 并将其传递到评论工厂,如果为空,它将抛出。
您只需传入 Id 并使用域事件处理程序验证其存在。如果不存在,则抛出。
您的数据库提供商在尝试添加具有无效 post id 的评论时将抛出 FK 违规。
无论是哪种情况,您都可以在命令处理程序(或命令处理管道)中捕获并将 PostNotFoundException 抛回给 API,然后可以 return 在 BadRequest 中处理。
尝试阅读更多关于 Layers in DDD 的内容,尤其是关于领域和应用层的内容。我认为您错过了一些核心概念,因为您的示例显示您试图在 API.
中实现业务逻辑在您的具体示例中,Domain 层负责检查您的聚合是否存在。您应该在命令处理程序中使用 Repository 模式(或类似模式)来获取聚合并在处理后保存它们。当找不到聚合时,存储库抛出异常。
P.S。 CQRS 模式完全是关于应用程序读写端的责任隔离,因此您不应在命令端使用read-model。