C# 架构精通 — ASP.NET Core 中的 CQRS(何时有帮助,何时有害)第9部分

发布: (2025年12月24日 GMT+8 05:03)
4 min read
原文: Dev.to

Source: Dev.to

Introduction

CQRS 是现代 .NET 中最容易被误解的模式之一。
有的团队过早采用它,有的团队因为担心而完全回避。这两种错误都源于把 CQRS 当作框架选择,而不是一种架构策略。

在本第 9 部分,我们将解释 CQRS 真正是什么、何时能带来清晰、何时会对 ASP.NET Core 系统产生负面影响。

What CQRS Stands For

Command Query Responsibility Segregation

  • Commands 改变状态
  • Queries 读取状态

这两种职责被分离。

What CQRS Does Not Require

  • 事件溯源(Event sourcing)
  • 微服务(Microservices)
  • 消息中间件(Message brokers)
  • 独立数据库(Separate databases)

这些是可选的——并非 CQRS 的核心。

Traditional CRUD Services

CRUD 服务通常把以下内容混在一起:

  • 读取
  • 写入
  • 验证
  • 业务规则
  • 映射逻辑
// ❌ CRUD service
class OrderService
{
    Order Get(int id) { }
    void Create(Order order) { }
    void Update(Order order) { }
}

随着系统规模的增长,这会导致:

  • 难以推理
  • 难以优化
  • 难以独立扩展

CQRS in Clean Architecture

  • Commands 位于 Application 层
  • Queries 位于 Application 层
  • 基础设施实现持久化
  • ASP.NET Core 将 HTTP 适配为 commands/queries

当边界已经存在时,CQRS 自然契合。

Commands

Commands 表示改变状态的意图。

public record CreateOrderCommand(decimal Total);

class CreateOrderHandler
{
    public Task Handle(CreateOrderCommand command) { }
}

Characteristics

  • 返回最少的数据(或不返回)
  • 包含验证
  • 强制业务规则

Queries

Queries 表示查询请求。

public record GetOrderQuery(int Id);

class GetOrderHandler
{
    public Task Handle(GetOrderQuery query) { }
}

Characteristics

  • 永不改变状态
  • 可以使用优化的读取模型
  • 常常绕过领域对象(有意为之)

When CQRS Is Beneficial

  • 读写模型差异显著
  • 查询性能至关重要
  • 业务规则复杂
  • 团队希望明确意图分离
  • 正在使用垂直切片架构(VSA)

CQRS 在中大型系统中表现突出。

When CQRS Hurts

  • 系统只是一个简单的 CRUD 应用
  • 团队缺乏架构纪律
  • 所有东西都变成 “handler” → 样板代码的负担超过价值

处理器激增的示例:

CreateUserCommandHandler
UpdateUserCommandHandler
DeleteUserCommandHandler
GetUserByIdQueryHandler
GetUsersQueryHandler

这可能会变成噪音而没有收益。

CQRS vs. MediatR

许多团队把 CQRS = MediatR,这是错误的认知。

  • MediatR 是一个消息库和便利工具。
  • CQRS 是一种设计决策和职责分离。

可以在不使用 MediatR 的情况下实现 CQRS。

CQRS Paired with Vertical Slice Architecture

每个切片包含:

  • Command 或 Query
  • Handler
  • Validator
  • Endpoint
Features/
 └─ Orders/
     ├─ Create/
     └─ GetById/

这降低了耦合度并提升了清晰度。

Adoption Checklist

在采用 CQRS 之前,先问自己:

  1. 读取和写入的演进是否不同?
  2. 性能是否真的成为问题?
  3. 领域复杂度是否在增长?
  4. 这会降低认知负担吗?
  5. 团队是否准备好遵守所需的纪律?

如果对任意问题的答案是 “否”,请推迟使用 CQRS。

Summary

  • CQRS 不是灵丹妙药。
  • 正确使用时: 明确意图,简化推理,优雅扩展。
  • 错误使用时: 增加仪式感,拖慢团队,掩盖简单逻辑。

资深工程师懂得何时使用它。

Back to Blog

相关文章

阅读更多 »