CQRS With MediatR In .NET 5

In this article, we are going to know a brief introduction to the CQRS pattern, and how the .NET library MediatR helps us build software.
 

CQRS and MediatR Pattern

 
The MediatR library was worked to work with two essential programming design designs: CQRS and the Mediator design. While comparative, we should spend a second understanding the standards behind each example.
 
Source Code - Git Hub Repo
 

CQRS (Command Query Responsibility Segregation)

 
In conventional information models, where peruses and composes are in synchronization sometimes with data sets, it turns out to be important to keep up the "Corrosive" properties relating to the information. Here comes the part of CQRS which means "Order Query Responsibility Segregation" which indicates that distinctive information models ought to be utilized for refreshing the data set and read from the data set. Order and Query are two tasks that represent read and composes individually.
 
Conventional tasks like CRUD – make, read, refresh and erase are standard activities completed on an informal basis consistently. Be that as it may, as our requirements become more modern, we go on to new and proficient methods of working with information. By isolating the order and question activities implies that tasks run on discrete legitimate cycles, presumably on different equipment. A change started in a data set courses to the order model for refreshing the information base and afterward the question model for perusing from the data set.
 
The principle utilization of the "CQRS" model being utilizing it in elite applications to scale peruse and compose activities. In this way, every technique ought to either be an order or be a question that performs separate activities however not both at the same time.
CQRS With MediatR In .NET 5

MediatR 

  • It’s an object that encapsulates how objects interact. So it can obviously handle passing on “messages” between objects.
  • It promotes loose coupling by not having objects refer to each other, but instead to the mediator. So they pass the messages to the mediator, who will pass it on to the right person.
CQRS With MediatR In .NET 5
Let's Start - Implementation,
 
Step 1 
 
Create a Solution with Web API Template (Version 5.0) make sure that you have the latest installed in your machine
 
Required Packages 
 
Click on Tools -> Nuget Package Manager -> Manage Nuget Packages for Solution.
 
CQRS With MediatR In .NET 5
 
Since we are not going with any database operations like fetching and storing from the Db. we need to setup hardcoded data in side the project for that i have created a folder named as Data and inside that we have to create to class files one is for acting as Model and other Repository Class to have the list of static Data. 
 
CQRS With MediatR In .NET 5
 
Simple Model where we having the three properties which we are utilizing for the list 
 
ToDo.cs
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Threading.Tasks;  
  5.   
  6. namespace CQRS_MediatrPattern_API.Data  
  7. {  
  8.     public class ToDo  
  9.     {  
  10.         public int Id { get; set; }  
  11.         public string Task { get; set; }  
  12.         public bool IsCompleted { get; set; }  
  13.     }  
  14. }  
Add the List of Static Data inside the Repository class by invoking the ToDo class.
 
Repository.cs
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Threading.Tasks;  
  5.   
  6. namespace CQRS_MediatrPattern_API.Data  
  7. {  
  8.     public class Repository  
  9.     {  
  10.         public List<ToDo> ToDos = new List<ToDo>  
  11.         {  
  12.             new ToDo{Id = 1, Task = "Cardio for 1 hour", IsCompleted = true},  
  13.             new ToDo{Id = 2, Task = "Make Breakfast", IsCompleted = true},  
  14.             new ToDo{Id = 3, Task = "Practivce Programming", IsCompleted = true},  
  15.             new ToDo{Id = 4, Task = "Power Nap for 30 Min", IsCompleted = false},  
  16.             new ToDo{Id = 5, Task = "Sending Emails", IsCompleted = false},  
  17.             new ToDo{Id = 6, Task = "Cook Dinner", IsCompleted = false},  
  18.         };  
  19.     }  
  20. }  

Configure the dependencies inside Startup.cs File

 
Startup.cs 
 
publicvoid ConfigureServices(IServiceCollection services)
  1.         {  
  2.   
  3.             services.AddControllers();  
  4.             services.AddSwaggerGen(c =>  
  5.             {  
  6.                 c.SwaggerDoc("v1"new OpenApiInfo { Title = "CQRS_MediatrPattern_API", Version = "v1" });  
  7.             });  
  8.             services.AddSingleton<Repository>();  
  9.             services.AddMediatR(typeof(Startup).Assembly);  
  10.         }  
Create an another folder in that we can add our Queries which will actually perform our business logic with support of MediatR & CQRS. So that i have created two classes where in one point to the GetData as (Get End point) and other as AddData (Post Endpoint).
 
CQRS With MediatR In .NET 5
 
Since i have segregated the statements inside the Class file the first thing is to add the Query property where we need to execute the Data and in the next line we have created a class called Handler where this has business logic and returns a response is handled by the record type (C# 9 Syntax)
 
1. Query - Accessing 
 
GetData.cs 
  1. using CQRS_MediatrPattern_API.Data;  
  2. using MediatR;  
  3. using System;  
  4. using System.Collections.Generic;  
  5. using System.Linq;  
  6. using System.Threading;  
  7. using System.Threading.Tasks;  
  8.   
  9. namespace CQRS_MediatrPattern_API.Queries  
  10. {  
  11.     public static class GetData  
  12.     {  
  13.         #region Query /Command  
  14.         //Data we need to execute  
  15.         public record Query(int Id) : IRequest<Response>;  
  16.         #endregion  
  17.   
  18.         #region Handler  
  19.         //Writing Business logic and returns response.  
  20.         public class Handler : IRequestHandler<Query, Response>  
  21.         {  
  22.             private readonly Repository _repository;  
  23.             public Handler(Repository repository)  
  24.             {     
  25.                 _repository = repository;  
  26.             }  
  27.             public async Task<Response> Handle(Query query, CancellationToken cancellationToken)  
  28.             {  
  29.                 var result = _repository.ToDos.FirstOrDefault(c => c.Id.Equals(query.Id));  
  30.                 return result == null ? null : new Response(result.Id, result.Task, result.IsCompleted);  
  31.             }  
  32.         }  
  33.         #endregion  
  34.   
  35.         #region Response  
  36.         //Data we want to return  
  37.             public record Response(int Id, string Task, bool IsCompleted);  
  38.         #endregion  
  39.     }  
  40. }  
2. Command - Passing
 
AddData.cs
  1. using CQRS_MediatrPattern_API.Data;  
  2. using MediatR;  
  3. using System;  
  4. using System.Collections.Generic;  
  5. using System.Linq;  
  6. using System.Threading;  
  7. using System.Threading.Tasks;  
  8.   
  9. namespace CQRS_MediatrPattern_API.Queries  
  10. {  
  11.     public static class AddData  
  12.     {  
  13.         //Command   
  14.         public record Command(string TaskName) :IRequest<ToDo>;  
  15.   
  16.         //Handler  
  17.         public class Handler : IRequestHandler<Command, ToDo>  
  18.         {  
  19.             private readonly Repository _repository;  
  20.   
  21.             public Handler(Repository repository)  
  22.             {  
  23.                 _repository = repository;  
  24.             }  
  25.             public async Task<ToDo> Handle(Command command, CancellationToken cancellationToken)  
  26.             {  
  27.                 var Todo = new ToDo { Id = 7, Task = "New Task", IsCompleted = false };  
  28.                 _repository.ToDos.Add(Todo);  
  29.                 return Todo;  
  30.             }  
  31.         }  
  32.     }  
  33. }  
Let's intergrate our End points by creating a controller class inside the Controller folder. 
 
TaskController.cs
  1. using CQRS_MediatrPattern_API.Data;  
  2. using CQRS_MediatrPattern_API.Queries;  
  3. using MediatR;  
  4. using Microsoft.AspNetCore.Http;  
  5. using Microsoft.AspNetCore.Mvc;  
  6. using System;  
  7. using System.Collections.Generic;  
  8. using System.Linq;  
  9. using System.Threading.Tasks;  
  10.   
  11. namespace CQRS_MediatrPattern_API.Controllers  
  12. {  
  13.     [ApiController]  
  14.     public class TaskController : ControllerBase  
  15.     {  
  16.         private readonly IMediator _mediatr;  
  17.         public TaskController(IMediator mediatr)  
  18.         {  
  19.             _mediatr = mediatr;  
  20.         }  
  21.         [HttpGet("/{Id}")]  
  22.         public async Task<IActionResult> GetDatabyId(int Id)  
  23.         {  
  24.             var result = await _mediatr.Send(new GetData.Query(Id));  
  25.             return result != null ? Ok(result) : NotFound();  
  26.         }  
  27.         [HttpPost("")]  
  28.         public async Task<IActionResult> GetDatabyId(AddData.Command command) => Ok(await _mediatr.Send(command));  
  29.     }  
  30. }   
Run & Test
 
Swagger is already configured in our project which is default if we are going with .Net 5.0 template will test our endpoints.
 
Get - API
CQRS With MediatR In .NET 5
 
Post - API
 
CQRS With MediatR In .NET 5
 
Hope this article helps you... !!
 
Keep Learning..... !