.NET 帮助 CQRS模式C#(开发人员如何使用) Curtis Chau 已更新:七月 28, 2025 Download IronPDF NuGet 下载 DLL 下载 Windows 安装程序 Start Free Trial Copy for LLMs Copy for LLMs Copy page as Markdown for LLMs Open in ChatGPT Ask ChatGPT about this page Open in Gemini Ask Gemini about this page Open in Grok Ask Grok about this page Open in Perplexity Ask Perplexity about this page Share Share on Facebook Share on X (Twitter) Share on LinkedIn Copy URL Email article 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 应用程序 启动 Visual Studio 并选择创建一个新项目。 搜索并选择“ASP.NET Core Web 应用程序”项目类型。点击下一步。 为您的项目命名并设置其位置。 选择 ASP.NET Core 的“Web 应用程序(模型-视图-控制器)”模板。确保您正在定位符合您要求的 .NET Core 版本。 点击创建。 步骤 2 接下来,您需要为 CQRS 组织您的项目。 点击创建。 您可以通过添加文件夹来分隔命令、查询和它们将使用的公共接口来完成这项工作。 在解决方案资源管理器中,右键单击您的项目,转到“添加”,然后选择“新建文件夹”。 创建三个文件夹:“Commands”、“Queries”和“Interfaces”。 在“Interfaces”文件夹中,为您的命令和查询添加接口。 对于命令,您可能会有一个接口 ICommandHandler,其中包含一个 Handle 方法,该方法接受命令并执行操作。 对于查询,您可能会有一个接口 IQueryHandler,其中包含一个 Handle 方法,该方法接收查询并返回数据。 ### 步骤 3 现在,让我们添加一个命令和查询来演示。 假设您的应用程序管理任务,您想添加一项任务(命令)并检索任务(查询)。 在“Interfaces”文件夹中,添加两个接口: 在“Commands”文件夹中,添加一个类 AddItemCommand,包含任务详细信息的属性。 同时,添加一个类 AddItemCommandHandler,它实现了 ICommandHandler 并包含将任务添加到数据库的逻辑。 // 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 $vbLabelText $csharpLabel 在“Queries”文件夹中,添加一个类 GetTasksQuery,表示对任务的请求。 再添加一个类 GetTasksQueryHandler,它实现了 IQueryHandler 并包含从数据库检索任务的逻辑。 作为一个简单的例子,您的 AddItemCommand 可能如下所示: 还有 AddItemCommandHandler: 您的 GetItemsQuery 如果不需要任何参数来获取任务,它可以是空的,而 GetItemsQueryHandler 可能如下所示: 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 $vbLabelText $csharpLabel 在您的 ASP.NET 控制器中,您将使用这些处理器处理命令和查询。 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 $vbLabelText $csharpLabel 对于添加任务,控制器操作将创建一个 AddTaskCommand,从表单数据中设置其属性,然后传递给一个 AddTaskCommandHandler 实例来处理。 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" }; } } } 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 $vbLabelText $csharpLabel 对于检索任务,它将调用一个 GetTasksQueryHandler 来获取数据并将其传递到视图。 ### 在控制器中连接它 设置好命令和查询后,您现在可以在控制器中使用它们。 以下是如何在ItemsController类中做到这一点: 要连接这一切,特别是在 ASP.NET Core 中使用依赖注入(DI)时,您需要在Startup.cs文件中向 DI 容器注册您的命令和查询处理器。这样,ASP.NET 在需要时可以提供您的处理器实例。 这里是一个注册处理器的非常基本的例子: 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 $vbLabelText $csharpLabel 在 CQRS 的实际应用中,写操作数据模型和读操作数据模型之间的区别是基础性的,这确保了架构支持多种优化方法来处理数据。 IronPDF: C# PDF 库 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)() $vbLabelText $csharpLabel 探索 IronPDF 用于 PDF 管理 是一个为使用 C# 编程语言的开发人员提供的工具,允许他们在其应用程序内部直接创建、读取和编辑 PDF 文档。 该库用户友好,使整合 PDF 功能(如生成 PDF 报告、发票或从 HTML 创建 PDF代码)更加简单。 IronPDF 支持多种功能,包括编辑 PDF 中的文本和图像、建立文档安全性和将网页转换为 PDF 格式。 其多功能性和易用性使其成为希望在项目中实现 PDF 操作的开发人员的宝贵资源。 IronPDF 以其HTML 到 PDF 的转换能力而著称,保持所有的布局和样式不变。 它从网页内容创建 PDF,适合报告、发票和文档。 HTML 文件、URL 和 HTML 字符串可以无缝地转换为 PDF。 现在,让我们探讨如何在遵循命令查询职责分离(CQRS)模式的 C# 应用程序中利用 IronPDF。 下面是一个简化示例,演示了如何在 CQRS 设置中使用 IronPDF 来生成 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 $vbLabelText $csharpLabel 代码示例 这个示例是概念性的,重点是作为命令生成 PDF 文档。 在此示例中,GeneratePdfReportCommand 表示 CQRS 模式中的命令。 它包括一个方法 GenerateReportAsync,接收 reportContent 作为 HTML 字符串和一个 outputPath,用于保存 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 $vbLabelText $csharpLabel IronPDF 的 HtmlToPdf 类被用于将 HTML 内容转换为 PDF 格式,然后保存到指定的路径。 此设置说明了如何将 PDF 生成功能整合到您的应用程序架构中,尤其是在要求清晰分离关注点的场景中,如 CQRS 所倡导的那样。 总结来说,命令查询职责分离(CQRS)模式为在应用程序中分离读写数据的责任提供了结构化的方法。 结论 这种分离不仅使架构更清晰,还提高了系统的灵活性、可扩展性和性能。 通过遵循上述步骤,您可以在 ASP.NET Core 应用程序中实现 CQRS,使用像 MediatR 这样的工具来简化命令、查询及其处理器之间的通信。 将 IronPDF 集成到您的基于 CQRS 的应用程序中,进一步拓宽了其功能,使您能够轻松创建、操作和存储 PDF 文档。 无论您是在生成报告、发票还是任何形式的文档,IronPDF 的全面功能和简单语法都使其成为开发工具箱中的强大工具。 IronPDF 提供了一个免费试用,让您有机会在投入之前探索其功能。 若要持续使用,许可证从$799起价,为您的项目需求提供多种选择。 IronPDF offers a free trial, giving you the chance to explore its capabilities before committing. For continued use, licenses start from $799, providing various options to match your project's needs. 常见问题解答 什么是软件开发中的CQRS模式? CQRS模式,全称命令查询职责分离,是一种将应用程序中的数据读取与写入分开的设计策略。这种分离允许独立优化命令(写入)和查询(读取)操作,从而增强性能和可扩展性。 CQRS如何提高.NET应用程序的性能? CQRS通过为读取和写入操作使用不同的数据模型来提高.NET应用程序的性能,从而使开发者能够独立优化各个部分。这提高了处理复杂业务逻辑的可扩展性和效率。 在CQRS设置中使用MediatR有什么优势? MediatR是一个中介者模式库,通过减少.NET应用程序中组件之间的耦合来促进CQRS。它作为一个中介,管理命令、查询及其处理程序之间的交互。 在C#应用程序中,IronPDF如何补充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提供免费试用版,允许开发者在购买决策前探索其功能和能力。 Curtis Chau 立即与工程团队聊天 技术作家 Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。除了开发之外,Curtis 对物联网 (IoT) 有浓厚的兴趣,探索将硬件和软件集成的新方法。在空闲时间,他喜欢玩游戏和构建 Discord 机器人,将他对技术的热爱与创造力相结合。 相关文章 已更新九月 4, 2025 RandomNumberGenerator C# 使用 RandomNumberGenerator C# 类可以帮助将您的 PDF 生成和编辑项目提升到一个新的高度。 阅读更多 已更新九月 4, 2025 C# String Equals(开发者用法) 与强大的 PDF 库 IronPDF 结合使用,切换模式匹配允许您为文档处理构建更智能、更简洁的逻辑。 阅读更多 已更新八月 5, 2025 C# Switch 模式匹配(开发者用法) 与强大的 PDF 库 IronPDF 结合使用,切换模式匹配允许您为文档处理构建更智能、更简洁的逻辑。 阅读更多 在C#中(开发人员如何使用)C# 单元测试(开发人员如...
已更新九月 4, 2025 RandomNumberGenerator C# 使用 RandomNumberGenerator C# 类可以帮助将您的 PDF 生成和编辑项目提升到一个新的高度。 阅读更多