.NET 帮助 CQRS模式C#(开发人员如何使用) Jacob Mellor 已更新:七月 28, 2025 下载 IronPDF NuGet 下载 DLL 下载 Windows 安装程序 免费试用 法学硕士副本 法学硕士副本 将页面复制为 Markdown 格式,用于 LLMs 在 ChatGPT 中打开 向 ChatGPT 咨询此页面 在双子座打开 向 Gemini 询问此页面 在双子座打开 向 Gemini 询问此页面 打开困惑 向 Perplexity 询问有关此页面的信息 分享 在 Facebook 上分享 分享到 X(Twitter) 在 LinkedIn 上分享 复制链接 电子邮件文章 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 在"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; } } 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 而 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 $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" }; } } } 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 在您的 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 $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>(); builder.Services.AddTransient(Of ICommandHandler(Of AddItemCommand), AddItemCommandHandler)() builder.Services.AddTransient(Of IQueryHandler(Of GetItemsQuery, IEnumerable(Of String)), GetItemsQueryHandler)() $vbLabelText $csharpLabel 在 CQRS 的实际应用中,写操作数据模型与读操作数据模型之间的区分是基础,确保架构支持多样化和优化的处理数据的方式。 IronPDF:C# PDF 库 !CQRS Pattern C# (开发人员如何使用):图 3 - IronPDF 网页 探索 IronPDF 进行 PDF 管理 是一个为使用 C# 编程语言的开发人员提供的工具,使他们能够直接在应用程序中创建、读取和编辑 PDF 文档。 该库用户友好,使生成 PDF 报告、发票或 从 HTML 创建 PDF 代码的 PDF 功能集成变得更简单。 IronPDF 支持各种功能,包括编辑 PDF 中的文本和图像、设置文档安全性以及将网页转换为 PDF 格式。 它的多功能性和易用性使其成为希望在项目中实现 PDF 操作的开发人员的宝贵资源。 IronPDF 在其 HTML 转 PDF 转换功能 方面表现出色,保持所有布局和样式不变。 它可以从 web 内容创建 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 $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); } } } 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 在这个示例中,GeneratePdfReportCommand 代表 CQRS 模式中的一个命令。 它包括一个方法 GenerateReportAsync,接受 reportContent 作为 HTML 字符串,以及一个 outputPath,PDF 报告将保存在此路径下。 IronPDF 的 HtmlToPdf 类用于将 HTML 内容转换为 PDF 格式,然后保存到指定路径。 这个设置说明了如何将 PDF 生成功能集成到您应用程序的架构中,特别是在需要按 CQRS 提倡的明确关注点分离的场景中。 !CQRS Pattern C# (开发人员如何使用):图 4 - 输出的 PDF 结论 !CQRS Pattern C# (开发人员如何使用):图 5 - IronPDF 许可证信息 最后,命令查询职责分离 (CQRS) 模式提供了一种结构化的方法,以在应用程序中分离读取和写入数据的职责。 这种分离不仅阐明了架构,还增强了您系统的灵活性、可扩展性和性能。 通过遵循上述步骤,您可以在ASP.NET Core应用程序中实现CQRS,使用像MediatR这样的工具来简化命令、查询及其处理程序之间的沟通。 将IronPDF集成到基于CQRS的应用程序中进一步扩展了其功能,使您能够轻松创建、操作和存储PDF文档。 若要持续使用,许可证从$799起价,为您的项目需求提供多种选择。 IronPdf 提供免费试用版,让您有机会在承诺之前探索其功能。 为便于持续使用,许可证从 $799 开始,提供各种选项以满足您的项目需求。 常见问题解答 什么是软件开发中的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提供免费试用版,允许开发者在购买决策前探索其功能和能力。 Jacob Mellor 立即与工程团队聊天 首席技术官 Jacob Mellor 是 Iron Software 的首席技术官,是 C# PDF 技术的先锋工程师。作为 Iron Software 核心代码库的原始开发者,自公司成立以来,他就塑造了公司的产品架构,并与首席执行官 Cameron Rimington 一起将其转变成一家公司,拥有50多人,服务于 NASA、特斯拉和全球政府机构。Jacob 拥有曼彻斯特大学 (1998-2001) 的一级荣誉土木工程学士学位。1999 年在伦敦创办了自己的第一家软件公司,并于 2005 年创建了他的第一个 .NET 组件后,他专注于解决微软生态系统中的复杂问题。他的旗舰 IronPDF 和 Iron Suite .NET 库在全球已获得超过 3000 万次的 NuGet 安装,其基础代码继续为全球使用的开发者工具提供支持。拥有 25 年商业经验和 41 年编程经验的 Jacob 仍专注于推动企业级 C#、Java 和 Python PDF 技术的创新,同时指导下一代技术领导者。 相关文章 已更新十二月 11, 2025 架起 CLI 简洁性与 .NET 的桥梁:使用 IronPDF for .NET 的 Curl DotNet Jacob Mellor 通过 CurlDotNet 填补了这一空白,CurlDotNet 库的创建是为了将 cURL 的熟悉感带入 .NET 生态系统。 阅读更多 已更新九月 4, 2025 RandomNumberGenerator C# 使用 RandomNumberGenerator C# 类可以帮助将您的 PDF 生成和编辑项目提升到一个新的高度。 阅读更多 已更新九月 4, 2025 C# String Equals(开发者用法) 与强大的 PDF 库 IronPDF 结合使用,切换模式匹配允许您为文档处理构建更智能、更简洁的逻辑。 阅读更多 在C#中(开发人员如何使用)C# 单元测试(开发人员如...
已更新十二月 11, 2025 架起 CLI 简洁性与 .NET 的桥梁:使用 IronPDF for .NET 的 Curl DotNet Jacob Mellor 通过 CurlDotNet 填补了这一空白,CurlDotNet 库的创建是为了将 cURL 的熟悉感带入 .NET 生态系统。 阅读更多
已更新九月 4, 2025 RandomNumberGenerator C# 使用 RandomNumberGenerator C# 类可以帮助将您的 PDF 生成和编辑项目提升到一个新的高度。 阅读更多