CQRS and Mediator Design Patterns

Darshana Mihiran Edirisinghe
4 min readOct 10, 2021

CQRS stands for Command Query Responsibility Segregation. This is for separate reads and writes operations in applications. In this pattern read processes are called ‘Queries’ and Write processes are called ‘Commands’. The simple meaning of this is to separate the read and write operations into individual classes.

When to use CQRS

As developers, if you really concern about the separation of concerns, single responsibility principle, etc. CQRS is a good choice. But it depends on the business problem which you are going to address. If the proposed system uses read operations heavily you can go for CQRS with better scalability since you can optimize the read database without making any changes to the write database. Also, you can use Redis to cache the readings.

Also, this adds more complexity to the system, and need to concern about the data consistency when you use multiple databases for reading and writing.

Example

Let’s assume that, in my project, I have two separate folders for commands and queries as follows.

The segregation between commands and queries

Inside the query folder, we have query handlers: GetEventByIdQueryHandler and GetEventsQueryHandler. According to the CQRS, these classes are queries and are used to read data from the database.

Query handlers

Inside of these classes, we can see Handler methods and we call the relevant repository method to get data. Handlers are part of the Mediator pattern.

GetEventQueryHandler class

We will discuss these things in the Mediator section. Same as in the Command folder we have handlers related to the write operations.

Command handlers

Same as in the previous one, we call the repository method inside the CreateEventCommandHandler: Handler method.

CreateEventCommandHandler class

Mediator Pattern

The mediator pattern helps to reduce the dependencies between objects. That is, objects should do the communication through the mediator to prevent direct communication between each other.

Services do not need to maintain dependencies on another service. The only dependency is with the mediator. The mediator handles the calls between each service. This results in less coupling among the classes since those don’t have dependencies with each other.

Mediator pattern also based on the Single Responsibility Principle, Open close principle, and Separation of Concerns.

To use the mediator pattern you need to install the MediatR NuGet package.

Install-Package MediatR -Version 9.0.0

Then we need to register the mediators in the startup class.

Register mediator in the startup class

After that, you need to inject the IMediator dependency into the controller class.

Event Controller

The basic idea behind this Mediator pattern is, every call has a request and handler. The request can be a data object that needs to be saved in the database or it can be an Id of a data object that needs to be retrieved from the database. The request should be sent to the handler and the handler will process the request.

Since I’m using the CQRS pattern, the request is either a command or query.

call handler method

In the Create event endpoint, we need to create a new order object as the ‘CreateEventCommand’ object and send it to the mediator.

CreateEventCommand class

The request: CreateEventCommand should be inherited from the IRequest interface and you need to add the return value type of the handler into the IRequest. Here is the Event type.

Thereafter, the send method calls the ‘CreateEventCommandHandler’. This handler should inherit from the ‘IRequestHandler<CreateEventCommand, Event>’ and using this TRequest and TResponse send method identifies the relevant Handler class.

CreateEventCommandHandler

Within the handler method, the ‘AddAsync’ repository method will call and create a new Event object and return it to the handler.

The mediator pattern is all about the reuse components and reduces the dependencies within the application.

--

--

Darshana Mihiran Edirisinghe

Full Stack Developer | Information Technology Consultant | Scrum Master | Tech Enthusiast