CQRS
Introduction
CQRS stands for Command Query Responsibility Segregation. You have the possibility to use this pattern thanks to MediatR.
When generating your application, you can choose to use CQRS. Enabling it will generate a new layer for your commands and queries called Application.
├── Namespace.Application
│ ├── Commands - Your commands
│ │ ├── MyEntity - Your entity
│ │ │ ├── MyEntityCreateCommand - A command
│ │ │ ├── MyEntityCreateCommandHandler - An handler for your command
│ ├── Queries - Your queries
│ │ ├── MyEntity - Your entity
│ │ │ ├── MyEntityGetQuery - A query
│ │ │ ├── MyEntityGetQueryHandler - An handler for your query
├── Namespace.Crosscutting
├── Namespace.Domain
├── Namespace.Domain.Services
├── Namespace.Dto
├── Namespace.Infrastructure
Create your own Queries or Commands
In order to create your own commands and/or queries you have to create two classes :
A command/query
An handler for it
For instance, let’s create a query MyEntityGetQuery.cs
:
namespace MyCompany.Application.Queries;
public class MyEntityGetQuery : IRequest<MyEntity>
{
public long Id { get; set; }
}
This Query should have an Id and returns a MyEntity object.
Here’s the handler MyEntityGetQueryHandler.cs
:
namespace MyCompany.Application.Queries;
public class MyEntityGetQueryHandler : IRequestHandler<MyEntityGetQuery, MyEntity>
{
private IReadOnlyMyEntityRepository _myEntityRepository;
public MyEntityGetQueryHandler(IReadOnlyMyEntityRepository myEntityRepository)
{
_myEntityRepository = myEntityRepository;
}
public Task<MyEntity> Handle(MyEntityGetQuery request,
CancellationToken cancellationToken)
{
return _myEntityRepository.QueryHelper()
.GetOneAsync(myEntity => myEntity.Id == request.Id);
}
}
Please note that we are using a ReadOnlyRepository rather than a service in order to do the segregation between Commands and Queries. Lastly, create your routing method within your controller :
[HttpGet("my-entity/{id}")]
public async Task<IActionResult> GetMyEntity([FromRoute] long id)
{
var result = await _mediator.Send(new MyEntityGetQuery { Id = id });
return ActionResultUtil.WrapOrNotFound(result);
}