什么是 API?
在了解什么是 CQRS 之前,我们首先了解 API。简而言之,API 就像一个接口,它是一组函数和方法,允许程序员访问应用程序的特定功能和数据。
Asp.Net Web API 的特点
- 它支持不同的 MVC 功能,如控制器、路由、模型绑定器、操作结果、过滤器、IOC 容器或依赖注入,这使得开发更简单、更容易。
- 我们可以创建由 Web API 的 MediaTypeFormatter 格式化为 XML 或 JSON 或您想要添加为 MediaTypeFormatter 的任何其他格式的 ASP.NET Web API。
- 它支持基于约定的创建、更新和删除操作,从中可以使用 HTTP 动词,如 GET、POST、PUT 和 DELETE。
- 我们可以以不同的方式创建 WebAPI,这些方式被接受并生成不像图像或任何其他文档文件那样面向对象的内容。
- ASP.NET Web API 在 HTTP 状态代码中给出响应。
- 它可以托管在应用程序或 IIS 上。
什么是 CQRS?
CQRS 代表“命令查询职责分离”。 CQRS 是 Greg Young 描述的一种模式。它的主要部分是您可以使用与用于读取信息的模型不同的模型来更新信息的概念。在某些情况下,这种分离通常很有价值,但请注意,对于许多系统,CQRS 会增加风险的复杂性。
人们用于与数据系统交互的主流方法是将其视为 CRUD 数据存储。我们的意思是我们有一个记录结构的模型,我们将在其中创建新记录,读取并更新它,并在完成记录后删除它们。在最简单的情况下,我们的交换就是存储和检索这些记录
随着我们的需求变得更加复杂,我们逐渐远离这种模式。我们可能希望在不同类型的记录存储中查看知识,可能将多个记录合并为一个,或者通过组合不同位置的信息来形成虚拟记录。
阅读更多: 了解 Asp.net Core 中的验证标签助手
CQRS 的好处
独立缩放
CQRS 允许读取和写入工作负载独立扩展,并且应该在更少的锁竞争中输出。
安全
命令查询职责分离更容易确认只有正确的域实体对数据执行写入。
关注点分离
区分读写端可能会导致模型更易于维护和灵活。所有硬业务逻辑都进入写入模型,读取模型很容易与写入模型进行比较。
更简单的查询
通过在读取数据库中存储物化视图,应用程序可以在查询时避免复杂的连接。
让我们开始用程序来允许 CQRS
要遵循我的示例,首先您需要从我的 GitHub 存储库中克隆我的项目。
从我的存储库完成克隆后,打开 CQRSDemo.sln 解决方案。
克隆我的项目代码后,让我们了解解决方案的结构
解决方案是带有一些手动包含文件夹的 ASP.NET 核心模板。在解决方案中有两个文件夹手动包含命令和查询。
在命令文件夹中,您将找到实现模式的命令部分的类,在查询文件夹中,您会找到与模式的查询部分相关的类。
控制器
在控制器中,你会发现 PostController 类有两个方法,第一个是 Get(),第二个是 SavePost() 方法。可以看到 Save 方法是作为命令实现的,第二个 Get 方法是作为查询实现的。
控制器类的代码如下。
[ApiController] public class PostsController :ControllerBase { private readonlyIQueriesService _queries; private readonlyICommandService _commands; public PostsController(IQueriesService queries, ICommandService commands) { _queries = queries ?? throw new ArgumentNullException(nameof(queries)); _commands = commands ?? throw new ArgumentNullException(nameof(commands)); } // GET api/values [HttpGet] public asyncTask<actionresult> Get() { return (await _queries.GetAllPostId()).ToList(); } // POST api/values [HttpPost] public void SavePost([FromBody] SavePostDto value) { _commands.SavePost(value.Title, value.Body); } }</actionresult>
如您所见,我们使用构造函数构建查询服务和命令服务在此控制器中完成。最初,我们首先配置 ASP.NET 核心依赖注入框架来处理所有相关情况。
在这个控制器中,Get 方法调用查询服务,savepost 方法调用命令服务。我们知道查询是只读的,而另一侧命令是修改系统状态的操作。
现在让我们看看这个服务是如何实现的。
命令文件夹
它包含一个接口,该接口说明了哪些命令服务能够用于基本实现。
下面是 ICommandService 接口:
public interface ICommandService { Task SavePost(string title, string body); } public class CommandService :ICommandService { private readonlyBlogContext _context; public CommandService(BlogContext context) { _context=context??throw new ArgumentNullException(nameof(context)); } public async Task SavePost(string title, string body) { var post = new Post() { Title = title, Body = body }; await _context.Posts.AddAsync(post ); await _context.SaveChangesAsync(); return post ; } }
此接口的实现基于将数据存储在 SQL 服务实例中的 Entity Framework Core。
想与我们技术精湛的.NET Core 开发人员交谈?现在联系。
查询
在 Command 文件夹中,您可以看到描述查询服务的 IQueriesService。
public interface IQueriesService { Task GetAllPostId(); }
IQueriesService 接口包含一个任务 GetAllPostId();方法来获取数据库中的唯一标识符。
public class QueriesService :IQueriesService { private readonly string _connectionString; public QueriesService(string connectionString) { if (string.IsNullOrEmpty(connectionString)) { throw new ArgumentException("message", nameof(connectionString)); } _connectionString = connectionString; } public async Task GetAllPostId() { using (var conn = new SqlConnection(_connectionString)) { conn.Open(); return await conn.QueryAsync("SELECT Id FROM dbo.Posts;"); } } }
正如您所看到的,查询和命令是不同的,并且对于只读技术是分开的,我们使用实体框架。
CQRS 的最大优势之一是我们可以构建高度优化的读取操作并区分不同数据存储的操作。
结论
我们希望通过这篇博文,您将全面了解 CQRS 模式以及如何在 API 中实现它并允许 CQRS 是一种模式。我们对不同模型中的命令和查询进行编程,它使用完整,易于实现和更优化的结构硬业务逻辑在写入模型中进行,读取模型很容易然后写入模型。简而言之,CQRS 是一种可以轻松读取和write 和 side 可能会导致模型更易于维护和灵活。