跳過到頁腳內容
.NET幫助

CQRS Pattern C#(對於開發者的運行原理)

CQRS的介紹

CQRS 代表命令查詢職責分離。 這是一種關注將數據的讀取與寫入分離的模式。 這種區分對於幾個原因來說是至關重要的。 首先,它允許對每個操作進行更靈活的優化,提高應用程序的性能和可擴展性。 當您分開命令(寫入)和查詢(讀取)時,您可以獨立地優化它們。

例如,一個複雜的應用程序可能需要快速的讀取操作,但可以接受較慢的寫入操作。 通過應用CQRS,開發者可以對讀寫使用不同的數據模型,分離數據訪問層,以滿足每個操作的特定需求。 在本文中,我們將探討CQRS模式的概念以及*IronPDF for .NET開發者的應用。

核心概念和組件

CQRS的核心在於將命令和查詢操作分開,各自處理不同方面的數據交互。 理解這些組件對於有效實施該模式至關重要。

  • 命令: 這些負責更新數據。 命令包含複雜的業務邏輯,能夠通過執行動作改變數據存儲中的數據狀態,且不返回任何信息。 命令專門處理寫入數據的任務,直接影響應用程序的狀態而不產生任何輸出。 例如,添加新用戶或更新現有產品的詳細信息都是由命令執行的操作。

  • 查詢: 由查詢處理器管理的查詢檢索數據或數據傳輸對象,不會改變系統的狀態。 它們是您詢問有關數據的問題。 例如,獲取用戶的個人資料或列出庫存中所有可用產品都是查詢操作。 查詢返回數據但確保它們不會修改數據或其狀態。

在.NET應用中實施CQRS的一個流行工具是MediatR,一個中介者模式庫。 它有助於減少應用程序組件之間的耦合,使其間接地進行通信。 MediatR通過在命令/查詢與其處理程序之間進行調解來促進命令和查詢的處理。

使用ASP.NET Core的實際實現

在ASP.NET Core中實現CQRS模式涉及到設置您的項目以分離命令和查詢,使用像MediatR這樣的庫在它們之間進行調解。 這裡有一個簡化的概述,說明如何在您的ASP.NET Core應用中設置CQRS。

步驟1:設置您的ASP.NET應用程序

  1. 啟動Visual Studio並選擇創建新項目。
  2. 搜索並選擇"ASP.NET Core Web Application"項目類型。 點擊下一步。

    CQRS模式C#(對開發者的作用):圖1 - 創建一個新的ASP.NET項目

  3. 為您的項目命名並設置其位置。 點擊創建。
  4. 選擇ASP.NET Core的"Web Application (Model-View-Controller)"模板。 確保您選擇符合要求的.NET Core版本。 點擊創建。

步驟2

接下來,您需要將項目組織化以適應CQRS。 您可以通過添加文件夾來分離命令、查詢及它們將使用的公共介面來實現這一點。 在解決方案資源管理器中,右鍵點擊您的項目,然後選擇"添加",之後選擇"新建文件夾"。 創建三個文件夾:"Commands"、"Queries"和"Interfaces"。

在"Interfaces"文件夾中,為您的命令和查詢添加介面。 對於命令,您可能需要一個介面ICommandHandler,其中包含一個方法Handle,用於接收命令並執行動作。 對於查詢,您可以擁有一個介面IQueryHandler,其中包含一個方法Handle,用於接收查詢並返回數據。

CQRS模式C#(對開發者的作用):圖2 - 文件如何組織的示例

步驟3

現在,讓我們添加一個命令和查詢來進行演示。 假設您的應用程序管理任務,並且您希望添加一項任務(命令)和檢索任務(查詢)。

在"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

在"Commands"文件夾中,添加一個類AddItemCommand,具有任務詳細信息的屬性。 另外,添加一個實現ICommandHandler的類AddItemCommandHandler,並包含將任務新增至數據庫的邏輯。

在"Queries"文件夾中,添加一個類GetTasksQuery,它代表了一個任務的請求。 添加另一個實現IQueryHandler的類GetTasksQueryHandler,並包含從數據庫檢索任務的邏輯。

對於一個簡單的例子,您的AddItemCommand可能看起來像這樣:

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

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

如果您的GetItemsQuery不需要任何參數來提取任務,它可能是空的,而GetItemsQueryHandler可能看起來像這樣:

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

在您的ASP.NET控制器中,您將使用這些處理器來處理命令和查詢。 為了添加一項任務,控制器操作將創建一個AddTaskCommand,從表單數據中設置其屬性,然後將其傳遞給一個AddTaskCommandHandler實例進行處理。 為了檢索任務,它將調用一個GetTasksQueryHandler以獲取數據並將其傳遞給視圖。

在控制器中將其連接起來

有了您的命令和查詢,您現在可以在控制器中使用它們。 在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

為了將一切連接起來,特別是如果您在ASP.NET Core中使用依賴注入(DI),您需要在Startup.cs文件中將命令和查詢處理器註冊到DI容器中。這樣,ASP.NET就能在需要時提供處理器的實例。

這是一個非常基本的註冊處理器的示例:

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

在CQRS的實際應用中,寫操作數據模型與讀操作數據模型之間的區分是基礎,確保了架構能支持以多樣化和最佳化的方式處理數據。

IronPDF: C# PDF庫

![CQRS模式C#(對開發者的作用):圖3 - IronPDF網頁](/static-assets/pdf/blog/cqrs-pattern-csharp/cqrs-pattern-csharp-3.webp)

探索IronPDF進行PDF管理 是一個針對使用C#編程語言的開發者的工具,允許他們直接在應用中創建、閱讀和編輯PDF文件。 該庫使用起來很友好,使得整合PDF功能變得更簡單,例如生成PDF報告、發票,或用HTML創建PDF代碼。 IronPDF支持各種功能,包括編輯PDF中的文字和圖片、設置文件安全性,以及將網頁內容轉換為PDF格式。 其多功能性和易用性使其成為開發者在專案中實施PDF操作的寶貴資源。

IronPDF具有HTML轉PDF轉換功能,能夠保留所有佈局和樣式完整性。 它從網頁內容創建PDF,適用於報告、發票和文件。 HTML文件、URL和HTML字符串可以順利轉換為PDFs。

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

代碼範例

現在,我們來探討如何在遵循命令查詢職責分離(CQRS)模式的C#應用中利用IronPDF。 下面是一個簡化的示例,展示了如何在CQRS設置中使用IronPDF來生成PDF報告。 此示例為概念性,著重於生成PDF文件作為命令。

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

在此示例中,GeneratePdfReportCommand代表CQRS模式中的一個命令。 它包含一個方法GenerateReportAsync,接收reportContent作為HTML字符串以及PDF報告將要儲存的outputPath。 IronPDF的HtmlToPdf類用於將HTML內容轉換為PDF格式,然後儲存到指定路徑中。 此設置說明了您如何將PDF生成功能整合到應用的架構中,特別是在需要明確關注點分離(CQRS提倡的)的情境中。

CQRS模式C#(對開發者的作用):圖4 - 輸出的PDF

結論

CQRS模式C#(對開發者的作用):圖5 - IronPDF授權信息

總結來說,命令查詢職責分離(CQRS)模式提供了一種將應用程式中讀和寫數據的責任分開的結構化方法。 這種分離不僅使架構更清晰,還能提高系統的靈活性、可擴展性和性能。 按照上述步驟,您可以在ASP.NET Core應用中實施CQRS,並使用像MediatR這樣的工具來簡化命令、查詢及其處理器之間的通信。

將IronPDF整合到您的基於CQRS的應用進一步擴展了其能力,使您能夠輕鬆地創建、操作和存儲PDF文件。 不論您是在生成報告、發票,還是任何形式的文件,IronPDF的全面功能和簡單易用的語法使其成為開發工具包中的強大工具。 IronPDF提供了一個免費試用,讓您有機會在購買前探索它的功能。 若要持續使用,授權從$799起,提供多種選項以滿足您的專案需求。

常見問題解答

什麼是軟體開發中的 CQRS 模式?

CQRS 模式,即指令查詢責任分離,是一種將應用程式中的資料讀取與寫入分離的設計策略。這種分離允許指令(寫入)和查詢(讀取)操作的獨立優化,提高了效能和擴展性。

CQRS 如何提高 .NET 應用程式的效能?

CQRS 通過為讀寫操作使用不同的資料模型來提高 .NET 應用程式的效能,使開發者可以獨立優化每個部分。這提高了處理複雜業務邏輯的可擴展性和效率。

在 CQRS 設置中使用 MediatR 有什麼優勢?

MediatR 是一個中介模式庫,它通過減少 .NET 應用程序中組件之間的耦合來促進 CQRS。它作為中介,管理命令、查詢及其處理程序之間的互動。

IronPDF 如何在 C# 應用程式中補充 CQRS 模式?

IronPDF 通過提供強大的 PDF 操作功能來補充 CQRS 模式。它允許開發者在應用程式中生成、讀取和編輯 PDF 檔案,非常適合在 CQRS 設置中作為指令操作的一部分來創建 PDF 報告。

為何在 ASP.NET Core 專案中分離指令和查詢是有益的?

在 ASP.NET Core 專案中分離指令和查詢可以增強組織性和清晰度。它允許開發者獨立管理每個方面,提高了可維護性並符合 CQRS 模式的原則。

依賴注入在 CQRS 架構中扮演什麼角色?

依賴注入在 CQRS 架構中至關重要,因為它允許無縫註冊和提供指令和查詢處理器。這確保 ASP.NET Core 應用程式能有效地解析依賴關係並根據需要管理處理器的實例。

如何在 C# 中使用庫將 HTML 轉換為 PDF?

您可以使用 IronPDF 的 RenderHtmlAsPdf 方法將 HTML 字串轉換為 PDF。它還支援使用 RenderHtmlFileAsPdf 將 HTML 文件轉換為 PDF,這對於生成報告和文件非常有用。

我可以在購買前評估 C# 的 PDF 庫嗎?

是的,IronPDF 提供免費的試用版,讓開發者在購買決策前探索其功能和特性。

Jacob Mellor, Team Iron 首席技術官
首席技術官

Jacob Mellor是Iron Software的首席技術官,也是開創C# PDF技術的前瞻性工程師。作為Iron Software核心代碼庫的原始開發者,他自公司成立以來就塑造了公司的產品架構,並與CEO Cameron Rimington將公司轉型為服務NASA、Tesla以及全球政府機構的50多人公司。

Jacob擁有曼徹斯特大學土木工程一級榮譽學士學位(1998年–2001年)。他於1999年在倫敦開立首家軟體公司,並於2005年建立了他的第一個.NET組件,專注於解決Microsoft生態系統中的複雜問題。

他的旗艦作品IronPDF和Iron Suite .NET程式庫全球已獲得超過3000萬次NuGet安裝,他的基礎代碼不斷在全球各地驅動開發者工具。擁有25年以上的商業經驗和41年的編碼專業知識,Jacob仍然專注於推動企業級C#、Java和Python PDF技術的創新,同時指導下一代技術領導者。

Iron Support Team

We're online 24 hours, 5 days a week.
Chat
Email
Call Me