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.
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.
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.
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.
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.
Simple Model where we having the three properties which we are utilizing for the list
ToDo.cs
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading.Tasks;
-
- namespace CQRS_MediatrPattern_API.Data
- {
- public class ToDo
- {
- public int Id { get; set; }
- public string Task { get; set; }
- public bool IsCompleted { get; set; }
- }
- }
Add the List of Static Data inside the Repository class by invoking the ToDo class.
Repository.cs
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading.Tasks;
-
- namespace CQRS_MediatrPattern_API.Data
- {
- public class Repository
- {
- public List<ToDo> ToDos = new List<ToDo>
- {
- new ToDo{Id = 1, Task = "Cardio for 1 hour", IsCompleted = true},
- new ToDo{Id = 2, Task = "Make Breakfast", IsCompleted = true},
- new ToDo{Id = 3, Task = "Practivce Programming", IsCompleted = true},
- new ToDo{Id = 4, Task = "Power Nap for 30 Min", IsCompleted = false},
- new ToDo{Id = 5, Task = "Sending Emails", IsCompleted = false},
- new ToDo{Id = 6, Task = "Cook Dinner", IsCompleted = false},
- };
- }
- }
Configure the dependencies inside Startup.cs File
Startup.cs
publicvoid ConfigureServices(IServiceCollection services)
- {
-
- services.AddControllers();
- services.AddSwaggerGen(c =>
- {
- c.SwaggerDoc("v1", new OpenApiInfo { Title = "CQRS_MediatrPattern_API", Version = "v1" });
- });
- services.AddSingleton<Repository>();
- services.AddMediatR(typeof(Startup).Assembly);
- }
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).
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
- using CQRS_MediatrPattern_API.Data;
- using MediatR;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading;
- using System.Threading.Tasks;
-
- namespace CQRS_MediatrPattern_API.Queries
- {
- public static class GetData
- {
- #region Query /Command
-
- public record Query(int Id) : IRequest<Response>;
- #endregion
-
- #region Handler
-
- public class Handler : IRequestHandler<Query, Response>
- {
- private readonly Repository _repository;
- public Handler(Repository repository)
- {
- _repository = repository;
- }
- public async Task<Response> Handle(Query query, CancellationToken cancellationToken)
- {
- var result = _repository.ToDos.FirstOrDefault(c => c.Id.Equals(query.Id));
- return result == null ? null : new Response(result.Id, result.Task, result.IsCompleted);
- }
- }
- #endregion
-
- #region Response
-
- public record Response(int Id, string Task, bool IsCompleted);
- #endregion
- }
- }
2. Command - Passing
AddData.cs
- using CQRS_MediatrPattern_API.Data;
- using MediatR;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading;
- using System.Threading.Tasks;
-
- namespace CQRS_MediatrPattern_API.Queries
- {
- public static class AddData
- {
-
- public record Command(string TaskName) :IRequest<ToDo>;
-
-
- public class Handler : IRequestHandler<Command, ToDo>
- {
- private readonly Repository _repository;
-
- public Handler(Repository repository)
- {
- _repository = repository;
- }
- public async Task<ToDo> Handle(Command command, CancellationToken cancellationToken)
- {
- var Todo = new ToDo { Id = 7, Task = "New Task", IsCompleted = false };
- _repository.ToDos.Add(Todo);
- return Todo;
- }
- }
- }
- }
Let's intergrate our End points by creating a controller class inside the Controller folder.
TaskController.cs
- using CQRS_MediatrPattern_API.Data;
- using CQRS_MediatrPattern_API.Queries;
- using MediatR;
- using Microsoft.AspNetCore.Http;
- using Microsoft.AspNetCore.Mvc;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading.Tasks;
-
- namespace CQRS_MediatrPattern_API.Controllers
- {
- [ApiController]
- public class TaskController : ControllerBase
- {
- private readonly IMediator _mediatr;
- public TaskController(IMediator mediatr)
- {
- _mediatr = mediatr;
- }
- [HttpGet("/{Id}")]
- public async Task<IActionResult> GetDatabyId(int Id)
- {
- var result = await _mediatr.Send(new GetData.Query(Id));
- return result != null ? Ok(result) : NotFound();
- }
- [HttpPost("")]
- public async Task<IActionResult> GetDatabyId(AddData.Command command) => Ok(await _mediatr.Send(command));
- }
- }
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
Post - API
Hope this article helps you... !!
Keep Learning..... !