IRONSOFTWAREHOME
開發者更新

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

Jacob Mellor,首席技術官 @ Team Iron
Jacob Mellor
Updated: 2026年4月21日

CQRS介紹

CQRS 代表指令查詢責任分離。 這是一種專注於分離資料的讀寫操作的模式。 這種區別至關重要,有多個原因。 首先,它允許更靈活地優化每個操作,提高應用性能和可擴展性。 當您分離指令(寫入)和查詢(讀取)時,可以獨立優化它們。

例如,一個複雜的應用程式可能需要快速的讀取操作,但可以容忍較慢的寫入操作。 通過應用CQRS,開發者可以使用不同的資料模型進行讀寫,將資料存取層分離以滿足每次操作具體的需求。 在本文中,我們將探討CQRS模式的概念以及IronPDF程式庫對.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應用"專案型別。 單擊下一步。

    CQRS模式C#(如何為開發者工作):圖1 - 建立新的ASP.NET專案

  3. 給您的專案命名並設置其位置。 按下建立。

  4. 選擇ASP.NET Core的"Web應用(模型-視圖-控制器)"模板。 確保您針對適合您需求的.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);
}

在"Commands"文件夾中新增一個類AddItemCommand,其中包含任務詳細資訊的屬性。 還要新增一個類AddItemCommandHandler,實現ICommandHandler並包含將任務新增到資料庫的邏輯。

在"Queries"文件夾中新增一個類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;
    }
}

以及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
    }
}

您的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" };
        }
    }
}

在您的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");
    }
}

要將所有內容連接起來,特別是如果您在ASP.NET Core中使用依賴注入(DI),您需要在Startup.cs文件中將您的指令和查詢處理程式註冊到DI容器中。這樣,ASP.NET在需要時可以提供處理程式的實例。

這裡是一個非常基本的註冊處理程式的例子:

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

在CQRS的實際應用中,寫操作的資料模型和讀操作的資料模型之間的區分是基礎,確保架構支持多樣化和優化的方法來處理資料。

IronPDF:C# PDF程式庫

CQRS模式C#(如何為開發者工作):圖3 - IronPDF網頁

探索IronPDF進行PDF管理 是一個供使用C#程式語言的開發者使用的工具,允許他們直接在其應用中建立、讀取和編輯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");
    }
}

程式碼範例

現在,讓我們探索IronPDF如何在遵循指令查詢責任分離(CQRS)模式的C#應用中使用。 下面是一個簡化的範例,展示在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);
        }
    }
}

在這個範例中,GeneratePdfReportCommand代表CQRS模式中的一個指令。 它包含一個方法GenerateReportAsync,接受reportContent作為一個HTML字串和一個outputPath,表示PDF報告將被保存的位置。 IronPDF的HtmlToPdf類用於將HTML內容轉換為PDF格式,然後保存到指定路徑。 此設置展示了如何將PDF生成功能整合到應用程式架構中,尤其是在需要明確責任分離的場景中,如CQRS所推廣的情況。

CQRS模式C#(如何為開發者工作):圖4 - 輸出的PDF

結論

總結一下,指令查詢責任分離(CQRS)模式提供了一種結構化的方法,將讀寫資料的責任分開在您的應用中。 這種分離不僅明確了架構,而且增強了系統的靈活性、可擴展性和性能。 通過遵循上述步驟,您可以在ASP.NET Core中實施CQRS,使用像MediatR這樣的工具來簡化指令、查詢及其處理程式之間的通信。

將IronPDF整合到您的基於CQRS的應用中進一步擴展其功能,使您可以輕鬆建立、操作和儲存PDF文件。 無論您是生成報告、發票或任何形式的文件,IronPDF全面的功能和簡單的語法使其成為您的開發工具包中的強大工具。 IronPDF提供了免費試用,讓您在決定是否承諾之前探索其功能。 要繼續使用,授權始於$999,提供多種選擇以匹配您專案的需求。

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

Jacob Mellor是Iron Software的首席技術官,一位在C# PDF技術上開創先河的遠見工程師。作為Iron Software核心程式碼庫的原開發者,他從創立以來就一直在塑造公司的產品架構,與首席執行官Cameron Rimington一起將公司轉變為服務於NASA、特斯拉和全球政府公司的50多名人員的公司。

...
閱讀更多

相關文章

Key in blue circle

立即免費取得 30 天試用金鑰

Your trial license will be sent to your email address

無任何限制。100% 解鎖。無需信用卡。

bullet_checked無需信用卡或建立帳號無任何限制。100% 解鎖。無需信用卡。
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
預訂您的免費現場演示
Booking Badge

受到全球數百萬工程師的信任

Iron Software的客戶標誌
獲取您的無義務諮詢
填寫以下表格或電子郵件sales@ironsoftware.com
您的詳細資訊將始終保密
受到全球數百萬工程師的信任
Iron Software的客戶標誌
立即獲取您的30天試用金鑰
無需信用卡或帳戶建立