Use Case: When applications change frequently, you can updated the Queries & Commands without affecting each other. When the Application is read heavy, you can then split the database into a Read (performance tuned for read) and Write (Fully normalized)
“The Command and Query Responsibility Segregation (CQRS) pattern separates read and update operations for a data store. Implementing CQRS in your application can maximize its performance, scalability, and security. The flexibility created by migrating to CQRS allows a system to better evolve over time and prevents update commands from causing merge conflicts at the domain level.”
CQRS has 3 building blocks
|Command / Query
|All the data we need to execute the Query or Command. This is represented as an object instance.
|Business logic to execute the Command or Query. This returns a response.
|Return data that we want to return encapsulated as an object.
All of the examples below are from Jonathan Williams: CQRS using C# and MediatR
Jonathan keeps the code together in a static class for findability and describes this as a container for the building blocks. Type of
record is recommended for
Responses as they are immutable, these are DTO’s (data transfer objects) so we dont want them to change.
All the code below has been simplified for brevity, the full source is on github. The
Repository is just a data repository that returns a
List<Todo> Todos where type
Todo is a domain entity with properties
- In a
Commandfolder create the static class
- Add the record
- In a
Queriesfolder create the static class
- Add the record
- In the controller use constructor injection to inject
IMediator mediator, then use
mediator.Send(requestObject)to infer the relative
- In the application startup pipeline add Mediator to the dependancy injection container using the extension method
AddMediatR. Passing the assembly
Startuptells mediator to use refection to include our classes above in the dependancy injection container (as they are in the same assembly as Startup). It will be looking for the
The order is important, any
Repository being used needs to be added to the container first as this will be resolved/injected into the handlers constructor.
Jonathan did a sweet video covering the code above.