Introduction
Each design pattern addresses issues related to software development. In this article, we will explore how to implement CQRS and Mediator in a. NET 8 Web API.
This article is suitable for beginners, intermediates, and professionals. We will cover,
- Introduction of CQRS
- Introduction of Mediator
- Step by Step implementation of CQRS and Mediator
Let’s start with, What is CQRS
Introduction of CQRS
CQRS stands for
- C – Command
- Q – Query
- R – Responsibility
- S- Segregation
This architecture pattern separates Read data and Write/Update data operations from each other.
Problem
In the big application, it is usual for applications to carry out numerous read/write operations; however, when the application’s users and the volume of operations increase dramatically, it is probable that the application will encounter problems like Scalability, Performance, Complexity, Flexibility, Consistency, etc.
Let’s see the below image.
![Application]()
Solution
Command Query Responsibility Segregation architecture pattern solves the problem and improves scalability, performance, flexibility, etc.
![Query Responsibility]()
Introduction of Mediator
The mediator design pattern seeks to minimize dependencies among objects by limiting direct interactions and instead establishing a means for them to work together solely through the mediator object. In simpler terms, an object exists that encapsulates and oversees the interactions between other objects.
Problem
Each application should be knowledgeable about the interface of the other applications, which will become challenging in the complex application. In this scenario, objects are closely interconnected with one another, making it difficult to manage the applications.
![Problem]()
Solution
The mediator pattern will address this issue. According to the image below, services can interact with each other via a mediator object rather than communicating directly with one another.
![Mediator]()
Now, we will implement CQRS +Mediator patterns using .NET Core 8.0.
Implementation of CQRS and Mediator
Step 1. Create a WeAbi project called “CQRDDemo”
Step 2. Install the Mediator nuget package.
![Install Mediator]()
Step 3. Configure the “Mediator R” Pattern in the Web API Project.
builder.Services.AddMediatR(config =>
config.RegisterServicesFromAssembly(typeof(Program).Assembly));
Step 4. Now, we will implement the "Member.cs" file.
public class Member
{
public int ID { get; set; }
public string Name { get; set; }
public string Address { get; set; }
}
Step 5. Create 1. “IDataAccess.cs” and “DataAccess.cs” files.
IDataAccess.cs
public interface IDataAccess
{
public Task<List<Member>> GetMembers();
public Task Member AddMember(int id, string name, string address);
}
DataAccess.cs
namespace CQRSDemo.DataAccess
{
public class DataAccess:IDataAccess
{
private List<Member> _member = new();|
public DataAccess()
{
_member.Add(new Member{ ID = 1, Name = "Kirtesh Shah", Address = "Vadodara" });
_member.Add(new Member{ ID = 2, Name = "Nitya Shah", Address = "Mumbai" });
}
public async Task Member AddMember(int id, string name, string address)
{
Member member = new Member { ID= id, Name = name, Address =address };
_member.Add(member);
await Task.CompletedTask;
}
public async Task<List<Member>> GetMembers()
{
return await Task.FromResult(member);
}
}
}
Step 6. Register dependencies in the program file.
builder.Services.AddScoped<IDataAccess, DataAccess>();
Step 7. Now we will create GetMemberQuery.cs
using CQRSDemo.DataAccess;
using MediatR;
namespace CQRSDemo.Query
{
public record GetMemberQuery(): IRequest<List<Member>>;
}
Step 8. Create the GetMemberHandler class and implement IRequestHandler provided by the Mediator R nuget package.
using CQRSDemo.DataAccess;
using MediatR;
namespace CQRSDemo.Query
{
public class GetMemberHandler: IRequestHandler<GetMemberQuery, List<Member>>
{
private readonly IDataAccess _dataAccess;
public GetMemberHandler(IDataAccess dataAccess)
{
_dataAccess = dataAccess;
}
}
async Task<List<Member>> IRequestHandler<GetMemberQuery, List<Member>>.Handle(GetMemberQuery request, CancellationToken cancellationToken) => await _dataAccess.GetMembers();
}
Step 9. Now we will implement MemberController.cs file.
using CQRSDemo.Query;
using MediatR;
using Microsoft.AspNetCore.Mvc;
namespace CORSDemo. Controllers
{
[Route("api/[controller]")]
[ApiController]
public class MemberController: ControllerBase
{
private readonly IMediator _mediator;
public MemberController (IMediator mediator)
{
_mediator = mediator;
}
[HttpGet]
public async Task<IActionResult> GetMembers()
{
var request = new GetMemberQuery();
var response= await _mediator.Send(request);
return Ok(response);
}
}
}
Step 10. Now, we will execute and verify the output.
![Output]()
Great! The query implementation is done, and we will implement the command now.
Step 11. Create “AddMemberCommand.cs”
using CQRSDemo.DataAccess;
using MediatR;
namespace CQRSDemo.Command
{
public record AddMemberCommand(Member Member): IRequest;
}
Step 12. Add "AddMemberHandler.cs" file.
using CQRSDemo.DataAccess;
using MediatR;
namespace CQRSDemo.Command
{
public class AddMemberHandler: IRequestHandler<AddMemberCommand>
{
private readonly IDataAccess dataAccess;
public AddMemberHandler(IDataAccess dataAccess)
{
_dataAccess dataAccess;
}
public async Task Handle (AddMemberCommand request,
CancellationToken cancellationToken) => await _dataAccess.AddMember(request.id, request.name, request.address);
}
}
Step 13. Now, make changes in the MemberController. Add HttpPost endpoint to add members in the lisṭ.
[HttpPost]
public async Task<IActionResult> AddMember([FromBody] Member member)
{
var response =_mediator.Send(new AddMemberCommand(member.ID, member.Name, member.Address));
return Ok(response);
}
Step 14. Execute and call the AddMember endpoint from the swagger.
![AddMember]()
Wow, so we have implemented CQRS and Mediator patterns using .Net 8.
Hope you enjoyed this article and find it useful.