Zum Fußzeileninhalt springen
.NET HILFE

CQRS-Muster C# (Funktionsweise für Entwickler)

Einführung in CQRS

CQRS steht für Command Query Responsibility Segregation. Es ist ein Muster, das sich darauf konzentriert, das Lesen von Daten vom Schreiben zu trennen. Diese Unterscheidung ist aus mehreren Gründen entscheidend. Erstens ermöglicht sie eine flexiblere Optimierung jeder Operation, was die Anwendungsleistung und Skalierbarkeit verbessert. Wenn Sie Befehle (Schreiben) und Abfragen (Lesen) trennen, können Sie sie unabhängig voneinander optimieren.

Zum Beispiel könnte eine komplexe Anwendung schnelle Leseoperationen erfordern, kann aber langsamere Schreiboperationen tolerieren. Durch die Anwendung von CQRS können Entwickler unterschiedliche Datenmodelle für Lese- und Schreibvorgänge verwenden und die Datenschicht an die spezifischen Bedürfnisse jeder Operation anpassen. In diesem Artikel werden wir die Konzepte des CQRS-Musters und die *IronPDF-Bibliothek für .NET-Entwickler erkunden.

Kernkonzepte und Komponenten

Der Kern von CQRS liegt in der Trennung von Befehl- und Abfrageoperationen, die jeweils unterschiedliche Aspekte der Dateninteraktion behandeln. Das Verständnis dieser Komponenten ist entscheidend für die effektive Implementierung des Musters.

  • Befehle: Diese sind für die Aktualisierung der Daten zuständig. Befehle verkörpern komplexe Geschäftslogik und können den Zustand der Daten im Datenspeicher ändern, indem sie ohne Rückgabe von Informationen agieren. Befehle übernehmen die ausschließliche Rolle der Bearbeitung von Schreibdatentasks und beeinflussen direkt den Zustand der Anwendung, ohne eine Ausgabe zu liefern. Zum Beispiel sind das Hinzufügen eines neuen Benutzers oder das Aktualisieren der Details eines vorhandenen Produkts Aktionen, die durch Befehle ausgeführt werden.

  • Abfragen: Abfragen, die von einem Abfragehandler verwaltet werden, rufen Daten oder Datentransferobjekte ab, ohne den Systemzustand zu verändern. Es sind die Fragen, die Sie zu Ihren Daten stellen. Zum Beispiel sind das Abrufen eines Benutzerprofils oder das Auflisten aller im Lager verfügbaren Produkte Abfragen. Abfragen geben Daten zurück, stellen jedoch sicher, dass sie die Daten oder deren Zustand nicht verändern.

Eines der beliebten Tools zur Implementierung von CQRS in .NET-Anwendungen ist MediatR, eine Bibliothek für das Vermittlermuster. Es hilft, die Kopplung zwischen Komponenten einer Anwendung zu reduzieren und sie indirekt kommunizieren zu lassen. MediatR erleichtert das Handling von Befehlen und Abfragen, indem es zwischen dem Befehl/der Abfrage und deren Handler vermittelt.

Praktische Umsetzung mit ASP.NET Core

Die Implementierung des CQRS-Musters in ASP.NET Core erfordert die Einrichtung Ihres Projekts, um Befehle und Abfragen zu trennen, indem Sie eine Bibliothek wie MediatR verwenden, um zwischen ihnen zu vermitteln. Hier ist eine vereinfachte Übersicht, wie Sie CQRS in Ihrer ASP.NET Core-Anwendung einrichten können.

Schritt 1: Richten Sie Ihre ASP.NET-Anwendung ein

  1. Starten Sie Visual Studio und wählen Sie, ein neues Projekt zu erstellen.
  2. Suchen Sie nach und wählen Sie den Projekttyp "ASP.NET Core Webanwendung". Drücken Sie Weiter.

CQRS-Muster C# (Wie es für Entwickler funktioniert): Abbildung 1 - Ein neues ASP.NET-Projekt erstellen

  1. Benennen Sie Ihr Projekt und legen Sie den Speicherort fest. Klicken Sie auf Erstellen.
  2. Wählen Sie das Template "Webanwendung (Model-View-Controller)" für ASP.NET Core. Stellen Sie sicher, dass Sie die .NET Core-Version anstreben, die Ihren Anforderungen entspricht. Klicken Sie auf Erstellen.

Schritt 2

Als nächstes möchten Sie Ihr Projekt für CQRS organisieren. Dies können Sie 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, wählen Sie "Hinzufügen" und dann "Neuer Ordner". Erstellen Sie drei Ordner: "Commands", "Queries" und "Interfaces".

Fügen Sie im Ordner "Interfaces" Schnittstellen für Ihre Befehle und Abfragen hinzu. Für einen Befehl könnten Sie eine Schnittstelle ICommandHandler mit einer Methode Handle haben, die einen Befehl annimmt und die Aktion durchführt. Für eine Abfrage könnten Sie eine Schnittstelle IQueryHandler mit einer Methode Handle haben, die eine Abfrage annimmt und Daten zurückgibt.

CQRS-Muster C# (Wie es für Entwickler funktioniert): Abbildung 2 - Beispiel, wie Dateien organisiert werden könnten

Schritt 3

Fügen wir einen Befehl und eine Abfrage zur Demonstration 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);
}
$vbLabelText   $csharpLabel

Fügen Sie im Ordner "Commands" eine Klasse AddItemCommand mit Eigenschaften für die Aufgabendetails hinzu. Fügen Sie auch eine Klasse AddItemCommandHandler hinzu, die ICommandHandler implementiert und die Logik enthält, um eine Aufgabe in die Datenbank hinzuzufügen.

Fügen Sie im Ordner "Queries" eine Klasse GetTasksQuery hinzu, die eine Anfrage für Aufgaben darstellt. Fügen Sie eine weitere Klasse GetTasksQueryHandler hinzu, die IQueryHandler implementiert und die Logik enthält, um Aufgaben aus der Datenbank abzurufen.

Für ein einfaches Beispiel könnte Ihr AddItemCommand so 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;
    }
}
$vbLabelText   $csharpLabel

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
    }
}
$vbLabelText   $csharpLabel

Ihre GetItemsQuery könnte leer sein, wenn sie keine Parameter benötigt, um Aufgaben abzurufen, und GetItemsQueryHandler könnte so aussehen:

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

In Ihren ASP.NET-Controllern verwenden Sie diese Handler, um Befehle und Abfragen zu verarbeiten. Für das Hinzufügen einer Aufgabe würde die Controller-Aktion einen AddTaskCommand erstellen, dessen Eigenschaften aus den Formulardaten übernehmen und dann an eine Instanz von AddTaskCommandHandler übergeben, um die Verarbeitung durchzuführen. Für das Abrufen von Aufgaben würde es einen GetTasksQueryHandler aufrufen, um die Daten zu erhalten und an die Ansicht weiterzuleiten.

Verkabelung in einem Controller

Mit Ihren eingerichteten Befehlen und Abfragen können Sie diese nun in Ihren Controllern verwenden. So könnten Sie dies in einer ItemsController-Klasse tun:

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

Um alles zu verbinden, besonders wenn Sie Dependency Injection (DI) in ASP.NET Core verwenden, müssen Sie Ihre Befehl- und Abfragehandler mit dem DI-Container in der Startup.cs-Datei registrieren. Auf diese Weise kann ASP.NET Instanzen Ihrer Handler bereitstellen, wenn sie benötigt werden.

Hier ist ein sehr einfaches Beispiel, wie ein Handler registriert wird:

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

In der praktischen Anwendung von CQRS ist die Unterscheidung zwischen dem Datenmodel für Schreiboperationen und dem für Leseoperationen grundlegend, um sicherzustellen, dass die Architektur verschiedene und optimierte Ansätze zur Datenverarbeitung unterstützt.

IronPDF: C# PDF-Bibliothek

CQRS-Muster C# (Wie es für Entwickler funktioniert): Abbildung 3 - IronPDF-Webseite

Erkunden Sie IronPDF für die PDF-Verwaltung ist ein Werkzeug für Entwickler, die mit der C#-Programmiersprache arbeiten, das es ihnen ermöglicht, PDF-Dokumente direkt innerhalb ihrer Anwendungen zu erstellen, zu lesen und zu bearbeiten. Diese Bibliothek ist benutzerfreundlich, was die Integration von PDF-Funktionen wie das Generieren von PDF-Berichten, Rechnungen oder Erstellen von PDFs aus HTML-Code vereinfacht. IronPDF unterstützt verschiedene Funktionen, einschließlich der Bearbeitung von Text und Bildern in PDFs, der Einrichtung von Dokumentsicherheit und der Umwandlung von Webseiten in 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 glänzt mit seiner HTML-zu-PDF-Konvertierungsfähigkeit und behält dabei alle Layouts und Stile bei. Es erstellt PDFs aus Webinhalten, geeignet für Berichte, Rechnungen und Dokumentationen. HTML-Dateien, URLs und HTML-Strings können nahtlos in PDFs umgewandelt 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");
    }
}
$vbLabelText   $csharpLabel

Codebeispiel

Nun, lassen Sie uns erkunden, wie IronPDF in einer C#-Anwendung im Rahmen des Command Query Responsibility Segregation (CQRS)-Musters genutzt werden kann. Unten ist ein vereinfachtes Beispiel, das zeigt, wie Sie IronPDF in einem CQRS-Setup verwenden können, um einen PDF-Bericht zu generieren. Dieses Beispiel ist konzeptionell und konzentriert sich auf die Generierung 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);
        }
    }
}
$vbLabelText   $csharpLabel

In diesem Beispiel stellt GeneratePdfReportCommand einen Befehl im CQRS-Muster dar. Es beinhaltet eine Methode GenerateReportAsync, die reportContent als HTML-String und einen outputPath entgegennimmt, wo der PDF-Bericht gespeichert wird. Die HtmlToPdf-Klasse von IronPDF wird verwendet, um den HTML-Inhalt in PDF-Format zu konvertieren, welches dann im angegebenen Pfad gespeichert wird. Dieses Setup veranschaulicht, wie Sie die PDF-Generierungsfunktion in die Architektur Ihrer Anwendung integrieren können, insbesondere in Szenarien, die eine klare Trennung der Verantwortlichkeiten erfordern, wie sie von CQRS gefördert werden.

CQRS-Muster C# (Wie es für Entwickler funktioniert): Abbildung 4 - Ausgegebenes PDF

Abschluss

CQRS-Muster C# (Wie es für Entwickler funktioniert): Abbildung 5 - IronPDF-Lizenzinformationen

Abschließend bietet das Command Query Responsibility Segregation (CQRS)-Muster einen strukturierten Ansatz zur Trennung der Verantwortlichkeiten von Lese- und Schreiboperationen in Ihren Anwendungen. Diese Trennung klärt nicht nur die Architektur, sondern verbessert auch die Flexibilität, Skalierbarkeit und Leistung Ihrer Systeme. Indem Sie die oben skizzierten Schritte befolgen, können Sie CQRS in Ihren ASP.NET Core-Anwendungen implementieren und Tools wie MediatR verwenden, um die Kommunikation zwischen Befehlen, Abfragen und ihren Handlern zu vereinfachen.

Die Integration von IronPDF in Ihre auf CQRS basierende Anwendung erweitert deren Fähigkeiten weiter und ermöglicht es Ihnen, mühelos PDF-Dokumente zu erstellen, zu manipulieren und zu speichern. Egal, ob Sie Berichte, Rechnungen oder jede Form von Dokumenten erstellen, die umfangreichen Funktionen und die einfache Syntax von IronPDF machen es zu einem leistungsstarken Werkzeug in Ihrem Entwicklungstoolkit. IronPDF bietet eine kostenlose Testversion, die Ihnen die Möglichkeit gibt, seine Fähigkeiten zu erkunden, bevor Sie sich verpflichten. Für die kontinuierliche Nutzung beginnen Lizenzen ab $799, und es stehen verschiedene Optionen zur Verfügung, die den Anforderungen Ihres Projekts entsprechen.

Häufig gestellte Fragen

Was ist das CQRS-Muster in der Softwareentwicklung?

Das CQRS-Muster, oder Command Query Responsibility Segregation, ist eine Designstrategie, die das Lesen von Daten vom Schreiben in Anwendungen trennt. Diese Trennung ermöglicht eine unabhängige Optimierung von Befehls- (Schreib-) und Abfrage- (Lese-) Operationen, was die Leistung und Skalierbarkeit verbessert.

Wie kann CQRS die Leistung in .NET-Anwendungen verbessern?

CQRS verbessert die Leistung in .NET-Anwendungen, indem es unterschiedliche Datenmodelle für Lese- und Schreiboperationen verwendet, sodass Entwickler jede Komponente unabhängig optimieren können. Dies führt zu besserer Skalierbarkeit und Effizienz bei der Handhabung komplexer Geschäftslogik.

Was sind die Vorteile der Verwendung von MediatR in einer CQRS-Einrichtung?

MediatR ist eine Mediator-Pattern-Bibliothek, die CQRS erleichtert, indem sie die Kopplung zwischen Komponenten in .NET-Anwendungen reduziert. Es fungiert als Vermittler und verwaltet die Interaktionen zwischen Befehlen, Abfragen und ihren Handlern.

Wie ergänzt IronPDF das CQRS-Muster in C#-Anwendungen?

IronPDF ergänzt das CQRS-Muster, indem es robuste PDF-Manipulationsmöglichkeiten bietet. Es ermöglicht Entwicklern, PDF-Dokumente innerhalb von Anwendungen zu generieren, zu lesen und zu bearbeiten, was es ideal macht, um PDF-Berichte als Teil von Befehlsoperationen in einer CQRS-Einrichtung zu erstellen.

Warum ist es vorteilhaft, Befehle und Abfragen in einem ASP.NET Core-Projekt zu trennen?

Die Trennung von Befehlen und Abfragen in einem ASP.NET Core-Projekt verbessert die Organisation und Klarheit. Es ermöglicht Entwicklern, jeden Aspekt unabhängig zu verwalten, verbessert die Wartbarkeit und passt zu den Prinzipien des CQRS-Musters.

Welche Rolle spielt die Dependency Injection in einer CQRS-Architektur?

Dependency Injection ist entscheidend in der CQRS-Architektur, da sie die nahtlose Registrierung und Bereitstellung von Befehl- und Abfrage-Handlern erlaubt. Dies stellt sicher, dass ASP.NET Core-Anwendungen effizient Abhängigkeiten auflösen und Instanzen von Handlern nach Bedarf verwalten können.

Wie kann ich HTML zu PDF in C# unter Verwendung einer Bibliothek umwandeln?

Sie können die RenderHtmlAsPdf-Methode von IronPDF verwenden, um HTML-Strings in PDFs umzuwandeln. Es unterstützt auch die Umwandlung von HTML-Dateien in PDFs mit RenderHtmlFileAsPdf, was nützlich für die Erstellung von Berichten und Dokumentationen ist.

Kann ich eine C# PDF-Bibliothek vor dem Kauf bewerten?

Ja, IronPDF bietet eine kostenlose Testversion an, die es Entwicklern ermöglicht, die Funktionen und Möglichkeiten zu erkunden, bevor sie eine Kaufentscheidung treffen.

Jacob Mellor, Chief Technology Officer @ Team Iron
Chief Technology Officer

Jacob Mellor ist Chief Technology Officer bei Iron Software und ein visionärer Ingenieur, der führend in der C# PDF-Technologie ist. Als ursprünglicher Entwickler der Iron Software-Kerncodebasis hat er die Produktarchitektur des Unternehmens seit seiner Gründung gestaltet und zusammen mit CEO Cameron Rimington in ein Unternehmen ...

Weiterlesen