For example: I want to delete an item or return 404 if it doesn't exist from a controller action. Am I breaking any rules? Commands are still separated from queries.
[ApiController]
public class PostsController : ControllerBase
{
[HttpDelete("/posts/{postId}")]
public async Task<IActionResult> DeletePost(Guid postId)
{
var postDTO = await _mediator.Send(new GetPostByIdQuery(postId)); // query
if (postDTO == null)
{
return NotFound();
}
await _mediator.Send(new DeletePostCommand(postId)); // command
return NoContent();
}
}
Not really specific to CQRS, but maybe?
If you are in the context of a controller, then you are in a world where we can reasonably expect that lots of different requests are being handled concurrently.
So we have to be aware that unlocked data can change out from under us while our process is running.
For something like a Delete, where we suspect that interest in a given postId is only happening in one place, then concurrency collisions are going to be rare, and maybe we don't need to worry about it.
In general... there's the potential for a real problem here.
Part of the problem here: your design here violates Tell, don't ask
Better might be a design that looks like:
This allows you to ensure that the read and the write are happening within the same transaction, which means you get the locking right.