Dans cet article, nous allons discuter du fonctionnement des modèles CQRS et MediatR et de la mise en œuvre étape par étape à l’aide de l’API Web .NET Core 6.
Conditions préalables
- Visual Studio 2022
- serveur SQL
- .NET Core 6
Introduction du modèle CQRS
- CQRS signifie Command and Query Responsibility Segregation et utilise pour séparer les lectures (requêtes) et les écritures (commandes).
- En cela, les requêtes effectuent une opération de lecture et la commande effectue une opération d’écriture comme créer, mettre à jour, supprimer et renvoyer des données.
- Comme nous le savons, dans notre application, nous utilisons principalement un modèle de données unique pour lire et écrire des données, ce qui fonctionnera correctement et effectuera facilement des opérations CRUD. Mais, lorsque l’application devient vaste dans ce cas, nos requêtes renvoient différents types de données en tant qu’objet, ce qui devient difficile à gérer avec différents objets DTO. En outre, le même modèle est utilisé pour effectuer une opération d’écriture. En conséquence, le modèle devient complexe.
- De plus, lorsque nous utilisons le même modèle pour les opérations de lecture et d’écriture, la sécurité est également difficile à gérer lorsque l’application est volumineuse, et l’entité peut exposer les données dans le mauvais contexte en raison de la charge de travail sur le même modèle.
- CQRS permet de découpler les opérations et de rendre l’application plus évolutive et flexible à grande échelle.
Quand utiliser le CQRS
- Nous pouvons utiliser Command Query Responsibility Segregation lorsque l’application est énorme et accéder aux mêmes données en parallèle. CQRS aide à réduire les conflits de fusion tout en effectuant plusieurs opérations avec les données.
- Dans la terminologie DDD, si le modèle de données de domaine est complexe et doit effectuer de nombreuses opérations en priorité, telles que des validations et l’exécution d’une logique métier, dans ce cas, nous avons besoin de la cohérence que nous obtiendrons en utilisant CQRS.
MédiatR
- Le modèle MediatR permet de réduire la dépendance directe entre plusieurs objets et de les rendre collaboratifs via MediatR.
- Dans .NET Core, MediatR fournit des classes qui aident à communiquer efficacement avec plusieurs objets de manière faiblement couplée.
Mise en œuvre étape par étape
Étape 1
Créer une nouvelle application.
Étape 2
Configurez votre application.
Étape 3
Fournissez des informations supplémentaires.

Étape 4
Structure du projet.
Étape 5
Installez les packages NuGet suivants.
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<Nullable>disable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="8.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="6.0.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
</ItemGroup>
</Project>
Étape 6
Créez une classe Student Details dans le dossier modèle.
namespace CQRSAndMediatRDemo.Models
{
public class StudentDetails
{
public int Id { get; set; }
public string StudentName { get; set; }
public string StudentEmail { get; set; }
public string StudentAddress { get; set; }
public int StudentAge { get; set; }
}
}
Étape 7
Ensuite, ajoutez DbContextClass dans le dossier de données.
using CQRSAndMediatRDemo.Models;
using Microsoft.EntityFrameworkCore;
namespace CQRSAndMediatRDemo.Data
{
public class DbContextClass : DbContext
{
protected readonly IConfiguration Configuration;
public DbContextClass(IConfiguration configuration)
{
Configuration = configuration;
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
}
public DbSet<StudentDetails> Students { get; set; }
}
}
Étape 8
Créez un référentiel d’étudiants et une classe liée à cela.
IStudentRepository
using CQRSAndMediatRDemo.Models;
namespace CQRSAndMediatRDemo.Repositories
{
public interface IStudentRepository
{
public Task<List<StudentDetails>> GetStudentListAsync();
public Task<StudentDetails> GetStudentByIdAsync(int Id);
public Task<StudentDetails> AddStudentAsync(StudentDetails studentDetails);
public Task<int> UpdateStudentAsync(StudentDetails studentDetails);
public Task<int> DeleteStudentAsync(int Id);
}
}
ÉtudiantRéférentiel
using CQRSAndMediatRDemo.Data;
using CQRSAndMediatRDemo.Models;
using Microsoft.EntityFrameworkCore;
using System;
using System.Numerics;
namespace CQRSAndMediatRDemo.Repositories
{
public class StudentRepository : IStudentRepository
{
private readonly DbContextClass _dbContext;
public StudentRepository(DbContextClass dbContext)
{
_dbContext = dbContext;
}
public async Task<StudentDetails> AddStudentAsync(StudentDetails studentDetails)
{
var result = _dbContext.Students.Add(studentDetails);
await _dbContext.SaveChangesAsync();
return result.Entity;
}
public async Task<int> DeleteStudentAsync(int Id)
{
var filteredData = _dbContext.Students.Where(x => x.Id == Id).FirstOrDefault();
_dbContext.Students.Remove(filteredData);
return await _dbContext.SaveChangesAsync();
}
public async Task<StudentDetails> GetStudentByIdAsync(int Id)
{
return await _dbContext.Students.Where(x => x.Id == Id).FirstOrDefaultAsync();
}
public async Task<List<StudentDetails>> GetStudentListAsync()
{
return await _dbContext.Students.ToListAsync();
}
public async Task<int> UpdateStudentAsync(StudentDetails studentDetails)
{
_dbContext.Students.Update(studentDetails);
return await _dbContext.SaveChangesAsync();
}
}
}
Étape 9
Après cela, ajoutez des requêtes de lecture.
GetStudentListQuery
using CQRSAndMediatRDemo.Models;
using MediatR;
namespace CQRSAndMediatRDemo.Queries
{
public class GetStudentListQuery : IRequest<List<StudentDetails>>
{
}
}
GetStudentByIdQuery
using CQRSAndMediatRDemo.Models;
using MediatR;
namespace CQRSAndMediatRDemo.Queries
{
public class GetStudentByIdQuery : IRequest<StudentDetails>
{
public int Id { get; set; }
}
}
Étape 10
Ensuite, créez différentes commandes.
CreateStudentCommandCreateStudentCommand
using CQRSAndMediatRDemo.Models;
using MediatR;
namespace CQRSAndMediatRDemo.Commands
{
public class CreateStudentCommand : IRequest<StudentDetails>
{
public string StudentName { get; set; }
public string StudentEmail { get; set; }
public string StudentAddress { get; set; }
public int StudentAge { get; set; }
public CreateStudentCommand(string studentName, string studentEmail, string studentAddress, int studentAge)
{
StudentName = studentName;
StudentEmail = studentEmail;
StudentAddress = studentAddress;
StudentAge = studentAge;
}
}
}
UpdateStudentCommandUpdateStudentCommand
using MediatR;
namespace CQRSAndMediatRDemo.Commands
{
public class UpdateStudentCommand : IRequest<int>
{
public int Id { get; set; }
public string StudentName { get; set; }
public string StudentEmail { get; set; }
public string StudentAddress { get; set; }
public int StudentAge { get; set; }
public UpdateStudentCommand(int id, string studentName, string studentEmail, string studentAddress, int studentAge)
{
Id = id;
StudentName = studentName;
StudentEmail = studentEmail;
StudentAddress = studentAddress;
StudentAge = studentAge;
}
}
}
Supprimer la commande de l’étudiant
using MediatR;
namespace CQRSAndMediatRDemo.Commands
{
public class DeleteStudentCommand : IRequest<int>
{
public int Id { get; set; }
}
}
Étape 11
Maintenant, ajoutez des gestionnaires de requêtes et de commandes.
GetStudentListHandler
using CQRSAndMediatRDemo.Models;
using CQRSAndMediatRDemo.Queries;
using CQRSAndMediatRDemo.Repositories;
using MediatR;
using System.Numerics;
namespace CQRSAndMediatRDemo.Handlers
{
public class GetStudentListHandler : IRequestHandler<GetStudentListQuery, List<StudentDetails>>
{
private readonly IStudentRepository _studentRepository;
public GetStudentListHandler(IStudentRepository studentRepository)
{
_studentRepository = studentRepository;
}
public async Task<List<StudentDetails>> Handle(GetStudentListQuery query, CancellationToken cancellationToken)
{
return await _studentRepository.GetStudentListAsync();
}
}
}
GetStudentByIdHandler
using CQRSAndMediatRDemo.Models;
using CQRSAndMediatRDemo.Queries;
using CQRSAndMediatRDemo.Repositories;
using MediatR;
using System.Numerics;
namespace CQRSAndMediatRDemo.Handlers
{
public class GetStudentByIdHandler : IRequestHandler<GetStudentByIdQuery, StudentDetails>
{
private readonly IStudentRepository _studentRepository;
public GetStudentByIdHandler(IStudentRepository studentRepository)
{
_studentRepository...