Implementación del patrón de segregación de responsabilidad de consultas y comandos CQRS
CQRS (Command Query Responsability Segregation) es un estilo arquitectónico en el que se separa las operaciones de lectura (Query) y actualización (Command) de un almacén de datos, el patrón CQRS puede maximizar su rendimiento, escalabilidad y seguridad de la aplicación. La flexibilidad creada al migrar a CQRS permite que un sistema evolucione mejor con el tiempo y evita que los comandos de actualización causen conflictos a nivel de dominio.
En este ejemplo implementaremos el patrón CQRS en un web api de .Net Core 3.1, la creación del proyecto se la realizará desde cero mediante lineas de comando, para este debe tener instalado .net core en su sistema operativo y disponible desde la línea de comandos.
Creación del proyecto
Desde la terminal o power shell ubicados en la carpeta donde queremos crear nuestro proyecto crearemos una solución ejecutando el comando dotnet new sln
el nombre de la solución será asignado automáticamente del nombre de la carpeta contenedora.
La aplicación estará separada en 4 capas, Dominio, Persistence, Application y la capa de Web API. Para lo cual crearemos librerías para cada capa.dotnet new class lib -n Domain
dotnet new class lib -n Persistence
dotnet new class lib -n Applicationdotnet new webapi -n API
Agregar librerías de clases a la solución y crear referencias
Para agregar la librería de clases a la solución debemos ejecutar los siguentes comandos desde la raiz del proyecto.dotnet sln add Domain/
dotnet sln add Persistence/
dotnet sln add Application/
Con el comando dotnet sln list
podemos verificar todas las librerías agregadas a nuestra solución. Hasta ahora tenemos la estructura de archivos que vamos a utilizar para implementar el patrón CQRS.
Ahora agregaremos las referencias de cada librería dentro del proyecto.
Application es la capa que se encargará de controlar la lógica de negocio tendrá una referencia con Domain y Persistence, lo agregaremos ejecutando el siguiente comando dentro de la librería Application.cd Application
dotnet add reference ../Domain/
dotnet add reference ../Persistence/
Web Api es la que se encargará de manejar las peticiones y devolver los datos al clientes tendrá la referencia únicamente con Application.cd API
dotnet add reference ../Application/
La capa de Persistence que es la encargada de las consultas y actualizaciones a la base de datos tendrá relación únicamente con Domain.cd Persistence/
dotnet add reference ../Domain/
Instalación de paquetes y configuración de DbContext
Primero debemos instalar los paquetes Nuget de EntityFrameworkCore para las consultas a la base de datos. Si está utilizando Visual Studio Code para la creación del proyecto se puede instalar la extensión NuGet Package Manager para instalar los paquetes necesarios, después de instalar la extensión se lo puede utilizar la consola para instalar los paquetes. Debemos instalar Microsoft.EntityframeworkCore en la librería de Persistence en la misma versión de net core utilizado en el proyecto en nuestro caso la 3.1. También se debe instalar Microsoft.EntityframeworkCore.Sqlite ya que utilizaremos la base de datos SqLite.
En el proyecto Domain crearemos una clase llamada Values, la cual será mapeada a la base de datos con los atributos que se muestran en la imagen.
El primer paso será crear nuestro DbContext que será donde configuraremos las entidades del dominio, par esto en el proyecto de Persistence creamos una nueva clase llamada DataContext.cs con el siguiente código.
Debemos registrar el DbContext en el Startup y configurar para utilizar la base de datos Sqlite.
En el paso anterior configuramos la cadena de conexión obteniendo el key DefaultConnection de nuestro archivo appsettings.json; debemos agregar está configuración de la siguiente manera.
"ConnectionStrings": {
"DefaultConnection":"Data source=reactivities.db"
},
dotnet ef migrations add InitialMigration -p Persistence/ -s API/

Instalación y configuración de MediatR
En el proyecto Application instalaremos el paquete MediatR.Extension.Microsoft.DependencyInjection en su versión 8.0.1, MediatR será el encargado de manejar y disparar nuestros commad y query.
En el proyecto Application crearemos una carpeta con el nombre de la entidad que crearemos el CRUD en nuestro caso una carpeta llamada Values. Dentro de está creamos una clase llamada List.cs
Ahora crearemos una clase llamada Create que ejecutará un command.
Registramos MediatR en nuestro Startup.
services.AddMediatR(typeof(List.Handler).Assembly);
Hasta ahora tenemos un Query llamado List que nos recuperará todos los datos de la base de datos y un Command Create que creará un registro en la base de datos, ahora debemos llamarlos desde un controller. En el proyecto WebApi crearemos un ValuesController; en el constructor inyectaremos IMediator para poder disparar nuestros command y query.
private readonly IMediator Mediator;
publicValuesController(IMediatormediator)
{
this.Mediator=mediator;
}
Agregaremos un action Get que disparará nuestro Query List y enviará al usuario la respuesta.
[HttpGet]
publicasyncTask<ActionResult<List<Value>>>Get()
{
returnawaitMediator.Send(newList.Query());
}
[HttpPost]
publicasyncTask<ActionResult<Unit>>PostAsync(Create.Commandcommand)
{
returnawaitMediator.Send(command);
}