Dapper 结合 MediatR 实现 CQRS 的本质是将读写逻辑剥离至职责清晰的 Handler:Dapper 以轻量高效方式执行原生 SQL,适配命令侧事务与查询侧性能需求,MediatR 通过管道行为统一处理日志、校验与异常,三层结构明确分离关注点。

用 Dapper 结合 MediatR 实现 CQRS,本质是把“写逻辑”和“读逻辑”从 API 层剥离,交给职责清晰的 Handler 去执行,而 Dapper 负责高效、可控地操作数据库。它不依赖复杂 ORM 的抽象,又比裸 ADO.NET 更简洁——刚好匹配 CQRS 对读写分离、轻量可控的要求。
Dapper 在命令(Command)侧的落地方式
命令操作关注数据变更、事务、业务校验。Dapper 的 Execute 方法天然适配这类场景,返回影响行数可直接用于结果判断。
- 在
IRequestHandler中,用 Dapper 执行 INSERT/UPDATE/DELETE SQL - 手动开启事务:通过
connection.BeginTransaction()包裹多个 Dapper 操作,确保一致性 - 参数绑定推荐使用匿名对象或强类型 DTO,避免字符串拼接;例如:
conn.Execute("UPDATE Bookings SET Status = @Status WHERE Id = @Id", new { Status = "Reserved", Id = cmd.Id }) - 命令 Handler 中不查业务状态?错——必要时可用 Dapper 同步查一次(比如检查库存是否充足),但不要做复杂 JOIN 或分页,那是 Query 的事
Dapper 在查询(Query)侧的典型用法
查询只读、高频、强调性能与灵活性。Dapper 的 Query 系列方法(Query、QueryFirst、QuerySingle、QueryMultiple)配合原生 SQL,能精准控制执行计划和映射行为。
- 定义
IRequestHandler,内部用 Dapper.QueryAsync直接映射结果 - 复杂报表类查询可搭配
QueryMultiple一次性拉取主子表数据,再手动组装 DTO,省去 N+1 和 EF 的延迟加载开销 - 避免在 Query Handler 中调用领域服务或触发领域事件——查询无副作用,这是 CQRS 的铁律
- 可结合缓存:比如用 IDistributedCache 缓存热门查询结果,Key 可基于查询参数哈希生成
MediatR 管道行为 + Dapper 的协同增效
MediatR 的管道行为(Pipeline Behavior)不是装饰器,而是对所有请求统一拦截的“横切点”。Dapper 本身不提供日志或异常包装,但借助 Behavior 就能低成本补全。
- LoggingBehavior:在 Execute 前后记录 SQL 语句(注意脱敏参数)、耗时、影响行数——这对排查慢查询和误更新极有用
- ValidatorBehavior:在命令进入 Dapper 执行前,校验 DTO 必填字段、格式、业务规则(如日期不能早于今天),失败直接返回错误,不碰数据库
- ExceptionBehavior:捕获 Dapper 抛出的 SqlException,统一转为 Result.Failure 或特定 API 错误码,避免敏感信息泄露
结构组织与依赖管理要点
代码怎么放,直接影响可维护性。CQRS 不是加一堆文件夹,而是让每层意图一目了然。
- Commands 和 Queries 分开命名空间,例如
Application.Bookings.Commands.ReserveBookingCommand和Application.Bookings.Queries.GetBookingQuery - Dapper 相关代码(如 IDbConnection 注入、SQL 文件管理)放在 Infrastructure 层,Application 层只依赖抽象接口(如
IDbConnectionFactory) - 注册 MediatR 时启用自动扫描:
services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(Program).Assembly));,Handler 类必须 public 且实现对应泛型接口 - 避免在 Handler 中 new SqlConnection —— 用 DI 注入连接工厂或已配置好的 connection(如带重试策略的 DbConnection)
基本上就这些。Dapper 提供肌肉,MediatR 提供神经,CQRS 提供骨架——三者合起来,不是堆技术,而是让每次数据库操作都目的明确、路径清晰、问题好追。










