跳至頁尾內容
.NET 幫助

C# CQRS 模式(開發者如何理解它)

CQRS簡介

CQRS代表指令查詢職責分離。 這是一種將資料讀取與資料寫入分開的模式。 這種區別至關重要,原因有幾點。 首先,它允許對每個操作進行更靈活的最佳化,從而提高應用程式的效能和可擴展性。 將命令(寫入)和查詢(讀取)分開,就可以分別對它們進行最佳化。

例如,複雜的應用程式可能需要快速的讀取操作,但可以容忍較慢的寫入操作。 透過應用 CQRS,開發人員可以使用不同的資料模型進行讀取和寫入,從而分離資料存取層,以滿足每個操作的特定需求。 在本文中,我們將探討 CQRS 模式和 .NET 開發人員的 *IronPDF 程式庫的概念。

核心概念和組成部分

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 應用程式"項目類型。 點選"下一步"。

    CQRS 模式 C#(開發者如何操作):圖 1 - 建立一個新的 ASP.NET 項目

  3. 為你的項目命名並設定其位置。 點擊"創建"。
  4. 選擇 ASP.NET Core 的"Web 應用程式(模型-視圖-控制器)"範本。 請確保您選擇的目標 .NET Core 版本符合您的需求。 點擊"創建"。

步驟 2

接下來,你需要為 CQRS 組織你的專案。 你可以透過將資料夾新增到不同的命令、查詢以及它們將使用的通用介面中來實現這一點。 在解決方案資源管理器中,右鍵單擊您的項目,轉到"新增",然後選擇"新資料夾"。 建立三個資料夾:"命令"、"查詢"和"介面"。

在"介面"資料夾中,新增指令和查詢的介面。 對於命令,您可以建立一個ICommandHandler接口,其中包含一個Handle方法,該方法接收命令並執行相應的操作。 對於查詢,您可以建立一個IQueryHandler接口,其中包含一個Handle方法,該方法接收查詢並傳回資料。

C# 中的 CQRS 模式(開發者如何理解):圖 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

在"命令"資料夾中,新增一個名為AddItemCommand 的類,並為其新增任務詳細資訊的屬性。 此外,新增一個實作ICommandHandler介面的AddItemCommandHandler類,其中包含向資料庫新增任務的邏輯。

在"查詢"資料夾中,新增一個名為GetTasksQuery 的類,該類表示任務請求。 新增另一個類別GetTasksQueryHandler,該類別實作IQueryHandler接口,並包含從資料庫中檢索任務的邏輯。

舉個簡單的例子,你的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 網頁

Explore IronPDF 是一款針對使用 C# 程式語言的開發人員的 PDF 管理工具,可讓他們直接在應用程式中建立、讀取和編輯 PDF 文件。 該程式庫易於使用,可以更輕鬆地整合 PDF 功能,例如產生 PDF 報告、發票或從 HTML 程式碼建立 PDF 。 IronPDF 支援多種功能,包括編輯 PDF 中的文字和圖像、設定文件安全性以及將網頁轉換為 PDF 格式。 它的多功能性和易用性使其成為開發人員在專案中實現 PDF 操作的寶貴資源。

IronPDF 的HTML 轉 PDF 功能非常出色,能夠保持所有佈局和樣式不變。 它可以根據網頁內容建立 PDF 文件,適用於報告、發票和文件。 HTML 檔案、URL 和 HTML 字串可以無縫轉換為 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");
    }
}
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 的方法,該方法接受一個 HTML 字串作為reportContent ,以及一個用於保存 PDF 報告的輸出路徑。 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 核心程式碼庫的最初開發者,他自公司成立之初便參與塑造了其產品架構,並與執行長 Cameron Rimington 一起將其發展成為一家擁有 50 多名員工、服務於 NASA、特斯拉和全球政府機構的公司。

Jacob 於 1998 年至 2001 年在曼徹斯特大學獲得土木工程一級榮譽學士學位。 1999 年,他在倫敦創辦了自己的第一家軟體公司;2005 年,他創建了自己的第一個 .NET 元件。此後,他專注於解決微軟生態系統中的複雜問題。

他的旗艦產品 IronPDF 和 IronSuite .NET 庫在全球 NuGet 上的安裝量已超過 3000 萬次,其基礎程式碼持續為全球開發者工具提供支援。憑藉 25 年的商業經驗和 41 年的程式設計專長,Jacob 始終致力於推動企業級 C#、Java 和 Python PDF 技術的創新,同時指導下一代技術領導者。