在生產環境中測試,無水印。
在任何需要的地方都能運行。
獲得 30 天的全功能產品。
在幾分鐘內上手運行。
試用產品期間完全訪問我們的支援工程團隊
CQRS 代表命令查詢責任分離。 這是一個專注於將讀取數據與寫入數據分離的模式。 這一區分出於多個原因而顯得尤為重要。 首先,它允許對每個操作進行更靈活的優化,提高應用程式的性能和可擴展性。 當您將命令(寫入)與查詢(讀取)分開時,可以分別優化它們。
例如,一個複雜的應用程式可能需要快速的讀取操作,但可以容忍較慢的寫入操作。 通過應用 CQRS,開發者可以對讀取和寫入使用不同的數據模型,將數據訪問層分隔開來,以滿足每個操作的具體需求。 在本文中,我們將探討 CQRS 模式的概念以及適用於 .NET 開發人員的 IronPDF 函式庫。
CQRS 的核心在於將命令操作和查詢操作分開,分別處理數據交互的不同方面。 了解這些組件對於有效地實施模式至關重要。
查詢:查詢由查詢處理程式管理,旨在檢索數據或數據傳輸對象,而不更改系統的狀態。 它們是您對數據提出的問題。 例如,查詢用戶的個人資料或列出庫存中所有可用產品都是查詢。 查詢返回數據,但確保它們不會修改數據或其狀態。
在 .NET 應用程序中實現 CQRS 的熱門工具之一是 MediatR,一個中介者模式庫。 它有助於減少應用程式元件之間的耦合,使它們間接交流。 MediatR 通過在命令/查詢和其處理器之間進行調解,促進命令和查詢的處理。
在 ASP.NET Core 中實現 CQRS 模式需要設置項目以分離命令和查詢,並使用類似 MediatR 的庫來進行中介。 以下是如何在您的 ASP.NET Core 應用程式中設置 CQRS 的簡化概述。
啟動 Visual Studio 並選擇建立一個新專案。
搜尋並選擇「ASP.NET Core Web 應用程式」專案類型。 點擊下一步。
為您的專案命名並設置其位置。 點擊建立。
接下來,您將需要為 CQRS 組織您的專案。 您可以透過新增資料夾來分隔命令、查詢及其將使用的通用介面來實現這一點。 在解決方案總管中,右鍵點擊您的專案,選擇「新增」,然後選擇「新資料夾」。 創建三個資料夾:“Commands”、“Queries”和“Interfaces”。
在「Interfaces」資料夾中,為您的命令和查詢新增介面。 對於一個命令,你可能會有一個介面ICommandHandler,其中有一個方法Handle,這個方法接收命令並執行動作。 對於查詢,您可以有一個介面IQueryHandler,其包含一個方法Handle,該方法接收查詢並返回資料。
現在,讓我們添加一個命令和查詢來演示。 假設您的應用程式管理任務,並且您想添加任務(命令)和檢索任務(查詢)。
在「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);
}
'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
在「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;
}
}
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
以及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
如果您的GetItemsQuery不需要任何參數來獲取任務,它可能是空的,而GetItemsQueryHandler可能看起來像:
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
在您的 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");
}
}
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
為了將所有內容連接起來,尤其是如果您在 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>();
builder.Services.AddTransient(Of ICommandHandler(Of AddItemCommand), AddItemCommandHandler)()
builder.Services.AddTransient(Of IQueryHandler(Of GetItemsQuery, IEnumerable(Of String)), GetItemsQueryHandler)()
在實際應用CQRS時,寫操作和讀操作的数据模型之間的區別是基礎,確保架構支持多樣化和優化的數據處理方法。
探索 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");
}
}
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
現在,我們來探討如何在遵循命令查詢責任分離(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);
}
}
}
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
在此範例中,GeneratePdfReportCommand 代表 CQRS 模式中的一個命令。 它包含一個方法 GenerateReportAsync,該方法接受reportContent作為HTML字符串及outputPath作為PDF報告保存的位置。 IronPDF 的 HtmlToPdf 類別用來將 HTML 內容轉換為 PDF 格式,然後保存到指定路徑。 此設置說明了如何將 PDF 生成功能整合到應用程式的架構中,特別是在需要明確分離關注點的 CQRS 案例中。
總結,命令查詢責任分離(CQRS)模式提供一種結構化的方法來分離應用程式中讀取和寫入資料的責任。 這種分離不僅澄清了架構,還增強了系統的靈活性、可擴展性和性能。 按照上述步驟操作,您可以在 ASP.NET Core 應用程式中實現 CQRS,使用像 MediatR 這樣的工具來簡化命令、查詢及其處理器之間的通信。
將 IronPDF 整合到基於 CQRS 的應用中,可以進一步擴展其功能,使您能夠輕鬆創建、操作和存儲 PDF 文件。 無論您是在生成報告、發票或任何形式的文件,IronPDF 的綜合功能和簡單明了的語法讓它成為您開發工具包中強大的工具。 IronPDF 提供免費試用,讓您在訂購前可先探索其功能。 若要繼續使用,授權費用從$749起,提供多種選項以配合您的專案需求。