CQRS Pattern With C# (Part 1)
Understand CQRS pattern in a real world application
CQRS is the acronym for Command Query Responsibility Segregation. The core idea of this pattern is to separate Read and Update operations by using different models to handle the treatment. We use commands to update data, and queries to read data.
In this article I’ll aim to clarify all parts of CQRS pattern with pretty schema and code example.
Traditional Architecture
The following schema shows a traditional architecture used to query and update a database. The same model is used to write and read data.
This architecture is perfect for a small project, but in more sophisticated applications, it will be laborious to implement new features. For example, the application needs to display some information on different screens. So, many queries are requested to database, then all responses are mapped to a specific data transfer object. Another example is when the application tries to update model with some data validation, maybe a complex business rules. In conclusion, the model does many things!
You will notice that the model becomes more and more complicated. To avoid this problem, let’s look at the contribution of the CQRS pattern in the next chapter.
New Architecture With CQRS
The CQRS pattern proposal, consists of separating the read and update / write operations into different models. As shown in the following schema,
two models are involved in this architecture, the first manages the read operations and the second manages the write operations.
According to Microsoft documentation, the CQRS pattern must follow the three principles below:
1) Commands should be task based, rather than data centric. (“Book hotel room”, not “set ReservationStatus to Reserved”).
2) Commands may be placed on a queue for asynchronous processing, rather than being processed synchronously.
3) Queries never modify the database. A query returns a DTO that does not encapsulate any domain knowledge.
Now, let’s take an example to explain all the concepts of CQRS.
Real World Application
I’ll try to create a simple application that follows the Domain-Driven Design (DDD) principles and use CQRS pattern to perform Read and Update operations. As shown in the following schema, the application is composed of four layers, UI, Application, Domain and Infrastructure.
The Application Layer encapsulates the use cases and features of the business. It provides communication with Domain and Infrastructure layers, it also includes commands and queries the two parts of CQRS.
Query Dispatcher and Command Dispatcher are used to choose a proper handler for a giving query/command and execute it.
The Query handler gets data from the repository and map the result with the appropriate DTO object. The Dispatcher is responsible to return data to UI.
The Command handler tries to validate data before making any changes to the system.
Here is the solution structure:
To manage commands and queries operations, I’m using the following interfaces:
Now, let’s try to explain one use case of the application, for example:
“Add a New Product”: this scenario is a command operation because it’ll make a change to the system.
First, I created a class called AddNewProductCommand
, this class is a simple DTO object that implement ICommand
.
Secondly, I created a class called AddNewProductCommandHandler
that implement ICommandHandler<T>
and used AddNewProductCommand
as input parameter to perform the user scenario.
Please notice that commands maybe processed asynchronously. To simplify this example I used an empty task to make the handler asynchronous.
Thirdly, I created a class called CommandDispatcher
that implement ICommandDispatcher
and used to choose a proper handler for a giving command. The handlers are injected using Microsoft.Extensions.DependencyInjection
.
Finally, in the code below, we can execute the command to add a new product. Another way to invoke this command is described on my project on GitHub, it’s about WebApi.
For other Scenarios, you can check the source code available on GitHub.
Conclusion
Implementing CQRS in your application can maximize its performance, such as reusability, testability, maintainability, security and scalability. However, it takes a lot of work to manage different models!
But don’t worry, MediatR library is here to simplify implementation of CQRS. My article about MediatR library is available here:
Thanks for reading. I hope this article was helpful to understand CQRS pattern.