Saltar al pie de página
.NET AYUDA

Patrón CQRS C# (Cómo Funciona para Desarrolladores)

Introducción a CQRS

CQRS significa Segregación de Responsabilidad de Comandos y Consultas. Es un patrón que se enfoca en separar la lectura de datos de su escritura. Esta distinción es crucial por varias razones. Primero, permite una optimización más flexible de cada operación, mejorando el rendimiento y la escalabilidad de la aplicación. Cuando separas los comandos (escrituras) y las consultas (lecturas), puedes optimizarlos de forma independiente.

Por ejemplo, una aplicación compleja puede requerir operaciones de lectura rápidas pero puede tolerar operaciones de escritura más lentas. Al aplicar CQRS, los desarrolladores pueden usar diferentes modelos de datos para las lecturas y escrituras, segregando la capa de acceso a datos para adaptarse a las necesidades específicas de cada operación. En este artículo, exploraremos los conceptos del patrón CQRS y la biblioteca *IronPDF para desarrolladores de .NET.

Conceptos básicos y componentes

El corazón de CQRS radica en separar las operaciones de comandos y consultas, cada una manejando diferentes aspectos de la interacción con los datos. Entender estos componentes es crucial para implementar el patrón de manera efectiva.

  • Comandos: Son los encargados de actualizar los datos. Los comandos encarnan lógica de negocio compleja y pueden cambiar el estado de los datos en el almacenamiento al actuar sin devolver ninguna información. Los comandos tienen el papel exclusivo de manejar las tareas de escritura de datos, influyendo directamente en el estado de la aplicación sin producir ninguna salida. Por ejemplo, agregar un nuevo usuario o actualizar los detalles de un producto existente son acciones realizadas por comandos.

  • Consultas: Las consultas, administradas por un controlador de consultas, recuperan datos u objetos de transferencia de datos sin cambiar el estado del sistema. Son las preguntas que haces sobre tus datos. Por ejemplo, obtener el perfil de un usuario o listar todos los productos disponibles en un inventario son consultas. Las consultas devuelven datos pero aseguran que no modifican los datos ni su estado.

Una de las herramientas populares para implementar CQRS en aplicaciones .NET es MediatR, una biblioteca de patrones mediadores. Ayuda a reducir el acoplamiento entre los componentes de una aplicación, permitiendo que se comuniquen de manera indirecta. MediatR facilita el manejo de comandos y consultas al mediar entre el comando/consulta y su manejador.

Implementación práctica con ASP.NET Core

Implementar el patrón CQRS en ASP.NET Core implica configurar tu proyecto para separar comandos y consultas, usando una biblioteca como MediatR para mediar entre ellos. Aquí hay una descripción simplificada de cómo puedes configurar CQRS en tu aplicación ASP.NET Core.

Paso 1: Configure su aplicación ASP.NET

  1. Inicia Visual Studio y elige crear un nuevo proyecto.
  2. Busca y selecciona un tipo de proyecto 'Aplicación Web ASP.NET Core'. Haz clic en Siguiente.

Patrón CQRS C# (Cómo Funciona Para Desarrolladores): Figura 1 - Creando un nuevo proyecto ASP.NET

  1. Dale un nombre a tu proyecto y establece su ubicación. Haga clic en Crear.
  2. Elige la plantilla 'Aplicación Web (Modelo-Vista-Controlador)' para ASP.NET Core. Asegúrate de que estás apuntando a la versión de .NET Core que se adapta a tus requisitos. Haga clic en Crear.

Paso 2

A continuación, querrás organizar tu proyecto para CQRS. Puedes hacerlo agregando carpetas para separar comandos, consultas y las interfaces comunes que usarán. En el Explorador de Soluciones, haz clic derecho en tu proyecto, ve a 'Agregar', luego 'Nueva Carpeta'. Crea tres carpetas: 'Comandos', 'Consultas' e 'Interfaces'.

En la carpeta 'Interfaces', agrega interfaces para tus comandos y consultas. Para un comando, podrías tener una interfaz ICommandHandler con un método Handle que toma un comando y realiza la acción. Para una consulta, podrías tener una interfaz IQueryHandler con un método Handle que toma una consulta y devuelve datos.

Patrón CQRS C# (Cómo Funciona Para Desarrolladores): Figura 2 - Ejemplo de cómo se podrían organizar los archivos

Paso 3

Ahora, vamos a agregar un comando y una consulta para demostrar. Supongamos que tu aplicación gestiona tareas, y quieres agregar una tarea (comando) y recuperar tareas (consulta).

En la carpeta 'Interfaces', agrega dos interfaces:

// Define interfaces for your handlers:
public interface ICommandHandler<TCommand>
{
    void Handle(TCommand command);
}

public interface IQueryHandler<TQuery, TResult>
{
    TResult Handle(TQuery query);
}
// Define interfaces for your handlers:
public interface ICommandHandler<TCommand>
{
    void Handle(TCommand command);
}

public interface IQueryHandler<TQuery, TResult>
{
    TResult Handle(TQuery query);
}
$vbLabelText   $csharpLabel

En la carpeta 'Comandos', agrega una clase AddItemCommand con propiedades para los detalles de la tarea. Además, agrega una clase AddItemCommandHandler que implemente ICommandHandler y contenga la lógica para agregar una tarea a la base de datos.

En la carpeta 'Consultas', agrega una clase GetTasksQuery que representa una solicitud de tareas. Agrega otra clase GetTasksQueryHandler que implemente IQueryHandler y contenga la lógica para recuperar tareas de la base de datos.

Para un ejemplo simple, tu AddItemCommand podría verse así:

public class AddItemCommand
{
    public string Name { get; set; }
    public int Quantity { get; set; }

    // Constructor
    public AddItemCommand(string name, int quantity)
    {
        Name = name;
        Quantity = quantity;
    }
}
public class AddItemCommand
{
    public string Name { get; set; }
    public int Quantity { get; set; }

    // Constructor
    public AddItemCommand(string name, int quantity)
    {
        Name = name;
        Quantity = quantity;
    }
}
$vbLabelText   $csharpLabel

Y el AddItemCommandHandler:

public class AddItemCommandHandler : ICommandHandler<AddItemCommand>
{
    public void Handle(AddItemCommand command)
    {
        // Here, you'd add the item to your database, for example, to have employee data stored
        Console.WriteLine($"Adding item: {command.Name} with quantity {command.Quantity}");
        // Add database logic here
    }
}
public class AddItemCommandHandler : ICommandHandler<AddItemCommand>
{
    public void Handle(AddItemCommand command)
    {
        // Here, you'd add the item to your database, for example, to have employee data stored
        Console.WriteLine($"Adding item: {command.Name} with quantity {command.Quantity}");
        // Add database logic here
    }
}
$vbLabelText   $csharpLabel

Tu GetItemsQuery podría estar vacío si no necesita ningún parámetro para obtener tareas, y GetItemsQueryHandler podría verse como:

public class GetItemsQuery
{
    // This class might not need any properties, depending on your query
}

namespace CQRS_testing.Queries
{
    using CQRS_testing.Interfaces;

    public class GetItemsQueryHandler : IQueryHandler<GetItemsQuery, IEnumerable<string>>
    {
        public IEnumerable<string> Handle(GetItemsQuery query)
        {
            // Here, you'd fetch items from your database
            return new List<string> { "Item1", "Item2" };
        }
    }
}
public class GetItemsQuery
{
    // This class might not need any properties, depending on your query
}

namespace CQRS_testing.Queries
{
    using CQRS_testing.Interfaces;

    public class GetItemsQueryHandler : IQueryHandler<GetItemsQuery, IEnumerable<string>>
    {
        public IEnumerable<string> Handle(GetItemsQuery query)
        {
            // Here, you'd fetch items from your database
            return new List<string> { "Item1", "Item2" };
        }
    }
}
$vbLabelText   $csharpLabel

En tus controladores ASP.NET, usarás estos manejadores para procesar comandos y consultas. Para agregar una tarea, la acción del controlador crearía un AddTaskCommand, establecería sus propiedades desde el formulario de datos, y luego lo pasaría a una instancia de AddTaskCommandHandler para manejarlo. Para recuperar tareas, llamaría a un GetTasksQueryHandler para obtener los datos y pasarlos a la vista.

Cableado en un controlador

Con tus comandos y consultas configurados, ahora puedes usarlos en tus controladores. Así es como podrías hacer eso en una clase ItemsController:

public class ItemsController : Controller
{
    private readonly ICommandHandler<AddItemCommand> _addItemHandler;
    private readonly IQueryHandler<GetItemsQuery, IEnumerable<string>> _getItemsHandler;

    // Constructor injection is correctly utilized here
    public ItemsController(ICommandHandler<AddItemCommand> addItemHandler, IQueryHandler<GetItemsQuery, IEnumerable<string>> getItemsHandler)
    {
        _addItemHandler = addItemHandler;
        _getItemsHandler = getItemsHandler;
    }

    public IActionResult Index()
    {
        // Use the injected _getItemsHandler instead of creating a new instance
        var query = new GetItemsQuery();
        var items = _getItemsHandler.Handle(query);
        return View(items);
    }

    [HttpPost]
    public IActionResult Add(string name, int quantity)
    {
        // Use the injected _addItemHandler instead of creating a new instance
        var command = new AddItemCommand(name, quantity);
        _addItemHandler.Handle(command);
        return RedirectToAction("Index");
    }
}
public class ItemsController : Controller
{
    private readonly ICommandHandler<AddItemCommand> _addItemHandler;
    private readonly IQueryHandler<GetItemsQuery, IEnumerable<string>> _getItemsHandler;

    // Constructor injection is correctly utilized here
    public ItemsController(ICommandHandler<AddItemCommand> addItemHandler, IQueryHandler<GetItemsQuery, IEnumerable<string>> getItemsHandler)
    {
        _addItemHandler = addItemHandler;
        _getItemsHandler = getItemsHandler;
    }

    public IActionResult Index()
    {
        // Use the injected _getItemsHandler instead of creating a new instance
        var query = new GetItemsQuery();
        var items = _getItemsHandler.Handle(query);
        return View(items);
    }

    [HttpPost]
    public IActionResult Add(string name, int quantity)
    {
        // Use the injected _addItemHandler instead of creating a new instance
        var command = new AddItemCommand(name, quantity);
        _addItemHandler.Handle(command);
        return RedirectToAction("Index");
    }
}
$vbLabelText   $csharpLabel

Para conectar todo, especialmente si estás usando Inyección de Dependencias (DI) en ASP.NET Core, necesitarás registrar tus manejadores de comandos y consultas con el contenedor DI en el archivo Startup.cs. De esta manera, ASP.NET puede proporcionar instancias de tus manejadores cuando se necesiten.

Aquí tienes un ejemplo muy básico de registro de un manejador:

builder.Services.AddTransient<ICommandHandler<AddItemCommand>, AddItemCommandHandler>();
builder.Services.AddTransient<IQueryHandler<GetItemsQuery, IEnumerable<string>>, GetItemsQueryHandler>();
builder.Services.AddTransient<ICommandHandler<AddItemCommand>, AddItemCommandHandler>();
builder.Services.AddTransient<IQueryHandler<GetItemsQuery, IEnumerable<string>>, GetItemsQueryHandler>();
$vbLabelText   $csharpLabel

En la aplicación práctica de CQRS, la distinción entre el modelo de datos para operaciones de escritura y el de operaciones de lectura es fundamental, asegurando que la arquitectura soporte enfoques variados y optimizados para manejar datos.

IronPDF: Biblioteca PDF C

Patrón CQRS C# (Cómo Funciona Para Desarrolladores): Figura 3 - Página web de IronPDF

Explora IronPDF para la gestión de PDFs es una herramienta para desarrolladores que trabajan con el lenguaje de programación C#, permitiéndoles crear, leer y editar documentos PDF directamente dentro de sus aplicaciones. Esta biblioteca es fácil de usar, lo que facilita la integración de funcionalidades PDF, como generar informes PDF, facturas o crear PDFs desde código HTML. IronPDF soporta varias características, incluyendo la edición de texto e imágenes en PDFs, establecer seguridad de documentos y convertir páginas web a formato PDF. Su versatilidad y facilidad de uso la convierten en un recurso valioso para los desarrolladores que buscan implementar operaciones PDF en sus proyectos.

IronPDF sobresale en su capacidad de conversión de HTML a PDF, manteniendo todos los diseños y estilos intactos. Crea PDFs desde contenido web, apropiados para informes, facturas y documentación. Archivos HTML, URLs y cadenas de HTML pueden ser convertidos a PDFs sin inconvenientes.

using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();

        // 1. Convert HTML String to PDF
        var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>";
        var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent);
        pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf");

        // 2. Convert HTML File to PDF
        var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file
        var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath);
        pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf");

        // 3. Convert URL to PDF
        var url = "http://ironpdf.com"; // Specify the URL
        var pdfFromUrl = renderer.RenderUrlAsPdf(url);
        pdfFromUrl.SaveAs("URLToPDF.pdf");
    }
}
using IronPdf;

class Program
{
    static void Main(string[] args)
    {
        var renderer = new ChromePdfRenderer();

        // 1. Convert HTML String to PDF
        var htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>";
        var pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent);
        pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf");

        // 2. Convert HTML File to PDF
        var htmlFilePath = "path_to_your_html_file.html"; // Specify the path to your HTML file
        var pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath);
        pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf");

        // 3. Convert URL to PDF
        var url = "http://ironpdf.com"; // Specify the URL
        var pdfFromUrl = renderer.RenderUrlAsPdf(url);
        pdfFromUrl.SaveAs("URLToPDF.pdf");
    }
}
$vbLabelText   $csharpLabel

Ejemplo de código

Ahora, exploremos cómo puede utilizarse IronPDF dentro de una aplicación C# siguiendo el patrón de Segregación de Responsabilidad de Comandos y Consultas (CQRS). A continuación hay un ejemplo simplificado que demuestra cómo podrías usar IronPDF dentro de una configuración CQRS para generar un informe PDF. Este ejemplo es conceptual y se enfoca en la generación de un documento PDF como un comando.

using IronPdf;
using System.Threading.Tasks;

namespace PdfGenerationApp.Commands
{
    public class GeneratePdfReportCommand
    {
        // Command handler that generates a PDF report
        public async Task GenerateReportAsync(string reportContent, string outputPath)
        {
            // Initialize the IronPDF HTML to PDF renderer
            var renderer = new ChromePdfRenderer();
            // Use IronPDF to generate a PDF from HTML content
            var pdf = await Task.Run(() => renderer.RenderHtmlAsPdf(reportContent));
            // Save the generated PDF to a specified path
            pdf.SaveAs(outputPath);
        }
    }
}
using IronPdf;
using System.Threading.Tasks;

namespace PdfGenerationApp.Commands
{
    public class GeneratePdfReportCommand
    {
        // Command handler that generates a PDF report
        public async Task GenerateReportAsync(string reportContent, string outputPath)
        {
            // Initialize the IronPDF HTML to PDF renderer
            var renderer = new ChromePdfRenderer();
            // Use IronPDF to generate a PDF from HTML content
            var pdf = await Task.Run(() => renderer.RenderHtmlAsPdf(reportContent));
            // Save the generated PDF to a specified path
            pdf.SaveAs(outputPath);
        }
    }
}
$vbLabelText   $csharpLabel

En este ejemplo, GeneratePdfReportCommand representa un comando en el patrón CQRS. Incluye un método GenerateReportAsync que toma reportContent como una cadena de HTML y un outputPath donde se guardará el informe PDF. La clase HtmlToPdf de IronPDF se utiliza para convertir el contenido HTML a formato PDF, que luego se guarda en la ruta especificada. Esta configuración ilustra cómo puedes integrar la funcionalidad de generación de PDF en la arquitectura de tu aplicación, especialmente en escenarios que requieren una clara separación de responsabilidades como lo promueve CQRS.

Patrón CQRS C# (Cómo Funciona Para Desarrolladores): Figura 4 - PDF generado

Conclusión

Patrón CQRS C# (Cómo Funciona Para Desarrolladores): Figura 5 - Información de la licencia de IronPDF

Para concluir, el patrón de Segregación de Responsabilidad de Comandos y Consultas (CQRS) ofrece un enfoque estructurado para separar las responsabilidades de lectura y escritura de datos en tus aplicaciones. Esta separación no solo aclara la arquitectura, sino que también mejora la flexibilidad, escalabilidad y rendimiento de tus sistemas. Siguiendo los pasos descritos anteriormente, puedes implementar CQRS en tus aplicaciones ASP.NET Core, utilizando herramientas como MediatR para agilizar la comunicación entre comandos, consultas y sus manejadores.

Integrar IronPDF en tu aplicación basada en CQRS amplía aún más sus capacidades, permitiéndote crear, manipular y almacenar documentos PDF sin esfuerzo. Ya sea que estés generando informes, facturas o cualquier forma de documento, las características comprehensivas y la sintaxis sencilla de IronPDF lo convierten en una herramienta poderosa en tu caja de herramientas de desarrollo. IronPDF ofrece una prueba gratuita, dándote la oportunidad de explorar sus capacidades antes de comprometerte. Para un uso continuo, las licencias comienzan desde $799, proporcionando varias opciones para adaptarse a las necesidades de tu proyecto.

Preguntas Frecuentes

¿Qué es el patrón CQRS en el desarrollo de software?

El patrón CQRS, o Segregación de Responsabilidad de Comandos y Consultas, es una estrategia de diseño que separa la lectura de datos de la escritura en aplicaciones. Esta separación permite la optimización independiente de las operaciones de comando (escritura) y consulta (lectura), mejorando el rendimiento y la escalabilidad.

¿Cómo puede mejorar el rendimiento de las aplicaciones .NET el CQRS?

CQRS mejora el rendimiento de las aplicaciones .NET utilizando modelos de datos distintos para las operaciones de lectura y escritura, lo que permite a los desarrolladores optimizar cada parte de manera independiente. Esto lleva a una mejor escalabilidad y eficiencia en el manejo de lógica de negocio compleja.

¿Cuáles son las ventajas de usar MediatR en una configuración CQRS?

MediatR es una biblioteca del patrón mediador que facilita CQRS al reducir el acoplamiento entre componentes en aplicaciones .NET. Actúa como intermediario, gestionando las interacciones entre comandos, consultas y sus manejadores.

¿Cómo complementa IronPDF el patrón CQRS en aplicaciones C#?

IronPDF complementa el patrón CQRS proporcionando capacidades robustas de manipulación de PDF. Permite a los desarrolladores generar, leer y editar documentos PDF dentro de aplicaciones, siendo ideal para crear informes PDF como parte de las operaciones de comando en una configuración CQRS.

¿Por qué es beneficioso separar comandos y consultas en un proyecto ASP.NET Core?

Separar comandos y consultas en un proyecto ASP.NET Core mejora la organización y claridad. Permite a los desarrolladores gestionar cada aspecto de manera independiente, mejorando la mantenibilidad y alineándose con los principios del patrón CQRS.

¿Qué papel juega la inyección de dependencia en una arquitectura CQRS?

La inyección de dependencia es crucial en una arquitectura CQRS ya que permite el registro y provisión sin problemas de manejadores de comandos y consultas. Esto asegura que las aplicaciones ASP.NET Core puedan resolver eficientemente las dependencias y gestionar instancias de manejadores según sea necesario.

¿Cómo puedo convertir HTML a PDF en C# usando una biblioteca?

Puede usar el método RenderHtmlAsPdf de IronPDF para convertir cadenas de HTML en PDFs. También admite la conversión de archivos HTML a PDFs usando RenderHtmlFileAsPdf, lo cual es útil para generar informes y documentación.

¿Puedo evaluar una biblioteca de PDF para C# antes de comprarla?

Sí, IronPDF ofrece una versión de prueba gratuita, permitiendo a los desarrolladores explorar sus características y capacidades antes de tomar una decisión de compra.

Jacob Mellor, Director de Tecnología @ Team Iron
Director de Tecnología

Jacob Mellor es Director de Tecnología en Iron Software y un ingeniero visionario que lidera la tecnología PDF en C#. Como el desarrollador original detrás de la base de código central de Iron Software, ha moldeado la arquitectura de productos de la compañía desde ...

Leer más