Test in einer Live-Umgebung
Test in der Produktion ohne Wasserzeichen.
Funktioniert überall, wo Sie es brauchen.
CQRS steht für Command Query Responsibility Segregation. Es handelt sich um ein Muster, bei dem das Lesen von Daten vom Schreiben getrennt wird. Diese Unterscheidung ist aus mehreren Gründen wichtig. Erstens ermöglicht es eine flexiblere Optimierung der einzelnen Vorgänge und verbessert so die Leistung und Skalierbarkeit der Anwendung. Wenn Sie Befehle trennen (schreibt) und Abfragen (liest)können Sie sie unabhängig voneinander optimieren.
Eine komplexe Anwendung kann zum Beispiel schnelle Lesevorgänge erfordern, aber langsamere Schreibvorgänge tolerieren. Durch die Anwendung von CQRS können Entwickler unterschiedliche Datenmodelle für Lese- und Schreibvorgänge verwenden und die Datenzugriffsschicht abtrennen, um sie an die spezifischen Anforderungen der einzelnen Vorgänge anzupassen. In diesem Artikel werden wir die Konzepte des CQRS-Musters und der IronPDF bibliothek.
Der Kern von CQRS liegt in der Trennung von Befehls- und Abfrageoperationen, die jeweils unterschiedliche Aspekte der Dateninteraktion behandeln. Das Verständnis dieser Komponenten ist entscheidend für die effektive Umsetzung des Musters.
Abfragen: Abfragen, die von einem Query-Handler verwaltet werden, rufen Daten oder Datenübertragungsobjekte ab, ohne den Zustand des Systems zu verändern. Das sind die Fragen, die Sie zu Ihren Daten stellen. Abfragen sind z. B. das Abrufen des Profils eines Benutzers oder die Auflistung aller in einem Bestand verfügbaren Produkte. Abfragen geben Daten zurück, stellen aber sicher, dass sie die Daten oder ihren Zustand nicht verändern.
Eines der beliebtesten Tools zur Implementierung von CQRS in .NET-Anwendungen ist MediatR, eine Mediator-Pattern-Bibliothek. Sie trägt dazu bei, die Kopplung zwischen den Komponenten einer Anwendung zu verringern, so dass sie indirekt miteinander kommunizieren. MediatR erleichtert die Bearbeitung von Befehlen und Abfragen, indem es zwischen dem Befehl/der Abfrage und seinem Bearbeiter vermittelt.
Bei der Implementierung des CQRS-Musters in ASP.NET Core müssen Sie Ihr Projekt so einrichten, dass Befehle und Abfragen voneinander getrennt werden, und eine Bibliothek wie MediatR verwenden, um zwischen ihnen zu vermitteln. Hier finden Sie eine vereinfachte Übersicht, wie Sie CQRS in Ihrer ASP.NET Core-Anwendung einrichten können.
Starten Sie Visual Studio und wählen Sie die Option zum Erstellen eines neuen Projekts.
Suchen Sie nach einem Projekttyp "ASP.NET Core Web Application" und wählen Sie ihn aus. Klicken Sie auf Weiter.
Geben Sie Ihrem Projekt einen Namen und legen Sie seinen Standort fest. Klicken Sie auf Erstellen.
Als nächstes müssen Sie Ihr Projekt für CQRS organisieren. Sie können dies tun, indem Sie Ordner hinzufügen, um Befehle, Abfragen und die gemeinsamen Schnittstellen, die sie verwenden, zu trennen. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf Ihr Projekt und wählen Sie "Hinzufügen" und dann "Neuer Ordner". Erstellen Sie drei Verzeichnisse: "Befehle", "Abfragen" und "Schnittstellen".
Fügen Sie im Ordner "Interfaces" Schnittstellen für Ihre Befehle und Abfragen hinzu. Für einen Befehl können Sie eine Schnittstelle ICommandHandler mit einer Methode Handle haben, die einen Befehl aufnimmt und die Aktion ausführt. Für eine Abfrage könnte man eine Schnittstelle IQueryHandler mit einer Methode Handle haben, die eine Abfrage aufnimmt und Daten zurückgibt.
Fügen wir nun zur Veranschaulichung einen Befehl und eine Abfrage hinzu. Angenommen, Ihre Anwendung verwaltet Aufgaben, und Sie möchten eine Aufgabe hinzufügen (befehl) und Aufgaben abrufen (abfrage).
Fügen Sie im Ordner "Interfaces" zwei Schnittstellen hinzu:
//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);
}
'Define interfaces for your handlers:
Public Interface ICommandHandler(Of TCommand)
Sub Handle(ByVal command As TCommand)
End Interface
Public Interface IQueryHandler(Of TQuery, TResult)
Function Handle(ByVal query As TQuery) As TResult
End Interface
Fügen Sie im Ordner "Commands" eine Klasse AddItemCommand mit Eigenschaften für die Aufgabendetails hinzu. Fügen Sie außerdem eine Klasse AddItemCommandHandler hinzu, die ICommandHandler implementiert und die Logik zum Hinzufügen einer Aufgabe zur Datenbank enthält.
Fügen Sie im Ordner "Queries" eine Klasse GetTasksQuery hinzu, die eine Anfrage nach Aufgaben darstellt. Fügen Sie eine weitere Klasse GetTasksQueryHandler hinzu, die IQueryHandler implementiert und die Logik zum Abrufen von Aufgaben aus der Datenbank enthält.
Ein einfaches Beispiel: Ihr AddItemCommand könnte wie folgt aussehen:
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;
}
}
Public Class AddItemCommand
Public Property Name() As String
Public Property Quantity() As Integer
' Constructor
Public Sub New(ByVal name As String, ByVal quantity As Integer)
Me.Name = name
Me.Quantity = quantity
End Sub
End Class
Und der 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
}
}
Public Class AddItemCommandHandler
Implements ICommandHandler(Of AddItemCommand)
Public Sub Handle(ByVal command As AddItemCommand)
' 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
End Sub
End Class
Ihre GetItemsQuery könnte leer sein, wenn sie keine Parameter zum Abrufen von Aufgaben benötigt, und GetItemsQueryHandler könnte wie folgt aussehen:
public class GetItemsQuery
{
// This class might not need any properties, depending on your query
}
using CQRS_testing.Interfaces;
namespace CQRS_testing.Queries
{
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
}
using CQRS_testing.Interfaces;
namespace CQRS_testing.Queries
{
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" };
}
}
}
Imports CQRS_testing.Interfaces
Public Class GetItemsQuery
' This class might not need any properties, depending on your query
End Class
Namespace CQRS_testing.Queries
Public Class GetItemsQueryHandler
Implements IQueryHandler(Of GetItemsQuery, IEnumerable(Of String))
Public Function Handle(ByVal query As GetItemsQuery) As IEnumerable(Of String)
' Here, you'd fetch items from your database
Return New List(Of String) From {"Item1", "Item2"}
End Function
End Class
End Namespace
In Ihren ASP.NET-Controllern werden Sie diese Handler verwenden, um Befehle und Abfragen zu verarbeiten. Um eine Aufgabe hinzuzufügen, würde die Controller-Aktion einen AddTaskCommand erstellen, seine Eigenschaften anhand der Formulardaten festlegen und ihn dann zur Bearbeitung an eine AddTaskCommandHandler-Instanz übergeben. Zum Abrufen von Aufgaben würde ein GetTasksQueryHandler aufgerufen, um die Daten abzurufen und sie an die Ansicht zu übergeben.
Nachdem Sie Ihre Befehle und Abfragen eingerichtet haben, können Sie sie nun in Ihren Steuerungen verwenden. Hier sehen Sie, wie Sie das in einer ItemsController-Klasse tun können:
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");
}
}
Public Class ItemsController
Inherits Controller
Private ReadOnly _addItemHandler As ICommandHandler(Of AddItemCommand)
Private ReadOnly _getItemsHandler As IQueryHandler(Of GetItemsQuery, IEnumerable(Of String))
' Constructor injection is correctly utilized here
Public Sub New(ByVal addItemHandler As ICommandHandler(Of AddItemCommand), ByVal getItemsHandler As IQueryHandler(Of GetItemsQuery, IEnumerable(Of String)))
_addItemHandler = addItemHandler
_getItemsHandler = getItemsHandler
End Sub
Public Function Index() As IActionResult
' Use the injected _getItemsHandler instead of creating a new instance
Dim query = New GetItemsQuery()
Dim items = _getItemsHandler.Handle(query)
Return View(items)
End Function
<HttpPost>
Public Function Add(ByVal name As String, ByVal quantity As Integer) As IActionResult
' Use the injected _addItemHandler instead of creating a new instance
Dim command = New AddItemCommand(name, quantity)
_addItemHandler.Handle(command)
Return RedirectToAction("Index")
End Function
End Class
Um alles zu verdrahten, insbesondere wenn Sie Dependency Injection verwenden (DI) in ASP.NET Core müssen Sie Ihre Befehls- und Abfrage-Handler mit dem DI-Container in der Datei Startup.cs registrieren. Auf diese Weise kann ASP.NET Instanzen Ihrer Handler bereitstellen, wenn sie benötigt werden.
Hier ist ein sehr einfaches Beispiel für die Registrierung eines Handlers:
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>();
builder.Services.AddTransient(Of ICommandHandler(Of AddItemCommand), AddItemCommandHandler)()
builder.Services.AddTransient(Of IQueryHandler(Of GetItemsQuery, IEnumerable(Of String)), GetItemsQueryHandler)()
In der praktischen Anwendung von CQRS ist die Unterscheidung zwischen dem Datenmodell für Schreiboperationen und dem für Leseoperationen von grundlegender Bedeutung, da sie sicherstellt, dass die Architektur unterschiedliche und optimierte Ansätze für den Umgang mit Daten unterstützt.
IronPDF ist ein Werkzeug für Entwickler, die mit der Programmiersprache C# arbeiten, mit dem sie PDF-Dokumente direkt in ihren Anwendungen erstellen, lesen und bearbeiten können. Diese Bibliothek ist benutzerfreundlich und vereinfacht die Integration von PDF-Funktionen wie die Erstellung von PDF-Berichten, Rechnungen oder Formulare aus HTML code. IronPDF unterstützt verschiedene Funktionen, darunter die Bearbeitung von Text und Bildern in PDF-Dateien, die Einrichtung der Dokumentensicherheit und die Konvertierung von Webseiten in das PDF-Format. Seine Vielseitigkeit und Benutzerfreundlichkeit machen es zu einer wertvollen Ressource für Entwickler, die PDF-Operationen in ihren Projekten implementieren möchten.
IronPDF zeichnet sich durch seine HTML zu PDF fähigkeit, wobei alle Layouts und Stile intakt bleiben. Es erstellt PDFs aus Webinhalten, die sich für Berichte, Rechnungen und Dokumentationen eignen. HTML-Dateien, URLs und HTML-Strings können nahtlos in PDFs konvertiert werden.
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");
}
}
Imports IronPdf
Friend Class Program
Shared Sub Main(ByVal args() As String)
Dim renderer = New ChromePdfRenderer()
' 1. Convert HTML String to PDF
Dim htmlContent = "<h1>Hello, IronPDF!</h1><p>This is a PDF from an HTML string.</p>"
Dim pdfFromHtmlString = renderer.RenderHtmlAsPdf(htmlContent)
pdfFromHtmlString.SaveAs("HTMLStringToPDF.pdf")
' 2. Convert HTML File to PDF
Dim htmlFilePath = "path_to_your_html_file.html" ' Specify the path to your HTML file
Dim pdfFromHtmlFile = renderer.RenderHtmlFileAsPdf(htmlFilePath)
pdfFromHtmlFile.SaveAs("HTMLFileToPDF.pdf")
' 3. Convert URL to PDF
Dim url = "http://ironpdf.com" ' Specify the URL
Dim pdfFromUrl = renderer.RenderUrlAsPdf(url)
pdfFromUrl.SaveAs("URLToPDF.pdf")
End Sub
End Class
Lassen Sie uns nun untersuchen, wie IronPDF innerhalb einer C#-Anwendung nach der Command Query Responsibility Segregation genutzt werden kann (CQRS) muster. Nachfolgend finden Sie ein vereinfachtes Beispiel, das zeigt, wie Sie IronPDF innerhalb einer CQRS-Einrichtung zur Erstellung eines PDF-Berichts verwenden können. Dieses Beispiel ist konzeptionell und konzentriert sich auf die Erzeugung eines PDF-Dokuments als Befehl.
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);
}
}
}
Imports IronPdf
Imports System.Threading.Tasks
Namespace PdfGenerationApp.Commands
Public Class GeneratePdfReportCommand
' Command handler that generates a PDF report
Public Async Function GenerateReportAsync(ByVal reportContent As String, ByVal outputPath As String) As Task
' Initialize the IronPDF HTML to PDF renderer
Dim renderer = New ChromePdfRenderer()
' Use IronPDF to generate a PDF from HTML content
Dim pdf = Await Task.Run(Function() renderer.RenderHtmlAsPdf(reportContent))
' Save the generated PDF to a specified path
pdf.SaveAs(outputPath)
End Function
End Class
End Namespace
In diesem Beispiel stellt GeneratePdfReportCommand einen Befehl nach dem CQRS-Muster dar. Sie enthält eine Methode GenerateReportAsync, die reportContent als HTML-String und einen outputPath, unter dem der PDF-Bericht gespeichert wird, entgegennimmt. Die Klasse HtmlToPdf von IronPDF wird verwendet, um den HTML-Inhalt in das PDF-Format zu konvertieren, das dann unter dem angegebenen Pfad gespeichert wird. Dieses Setup veranschaulicht, wie Sie PDF-Generierungsfunktionen in die Architektur Ihrer Anwendung integrieren können, insbesondere in Szenarien, die eine klare Trennung von Belangen erfordern, wie sie von CQRS gefördert wird.
Zusammenfassend lässt sich sagen, dass der Befehl Query Responsibility Segregation (CQRS) muster bietet einen strukturierten Ansatz, um die Verantwortlichkeiten für das Lesen und Schreiben von Daten in Ihren Anwendungen zu trennen. Diese Trennung verdeutlicht nicht nur die Architektur, sondern erhöht auch die Flexibilität, Skalierbarkeit und Leistung Ihrer Systeme. Wenn Sie die oben beschriebenen Schritte befolgen, können Sie CQRS in Ihre ASP.NET Core-Anwendungen implementieren und Tools wie MediatR verwenden, um die Kommunikation zwischen Befehlen, Abfragen und ihren Handlern zu optimieren.
Die Integration von IronPDF in Ihre CQRS-basierte Anwendung erweitert deren Möglichkeiten und ermöglicht Ihnen, mühelos PDF-Dokumente zu erstellen, zu bearbeiten und zu speichern. Ganz gleich, ob Sie Berichte, Rechnungen oder andere Dokumente erstellen, die umfassenden Funktionen und die einfache Syntax von IronPDF machen es zu einem leistungsstarken Werkzeug in Ihrem Entwicklungs-Toolkit. IronPDF bietet eine kostenlos testenso haben Sie die Möglichkeit, die Möglichkeiten des Systems zu testen, bevor Sie sich festlegen. Für die fortgesetzte Nutzung beginnen die Lizenzen bei $749 und bieten verschiedene Optionen, um den Anforderungen Ihres Projekts zu entsprechen.
9 .NET API-Produkte für Ihre Bürodokumente