C#如何实现CQRS模式 MediatR库入门与实践指南

幻夢星雲
发布: 2025-12-19 12:22:33
原创
191人浏览过
MediatR是C#中实现CQRS最轻量主流的选择,以“请求-响应”模型分离命令与查询,提升可测性与扩展性;它作为进程内消息总线自动路由请求到唯一处理器,不强制接口,需自行组合事务、缓存等能力。

c#如何实现cqrs模式 mediatr库入门与实践指南

在C#中实现CQRS模式,MediatR是最轻量、最主流的选择之一。它不强制你写一堆接口和基类,而是用“请求-响应”模型自然地把命令(Command)和查询(Query)分开,让业务逻辑更清晰、可测试性更强、扩展更灵活。

一、理解CQRS与MediatR的核心分工

CQRS(Command Query Responsibility Segregation)本质是把“改数据”和“读数据”彻底拆开:命令负责修改状态(如创建订单、更新用户),查询只负责返回数据(如获取用户列表、查订单详情)。MediatR不是CQRS框架,而是一个进程内消息总线——它帮你把请求(IRequest)发给唯一对应的处理器(IRequestHandler),自动完成路由、依赖注入和生命周期管理。

关键点:

  • 一个请求类型(比如CreateUserCommand)只能有一个处理器;
  • 查询和命令都用IRequest<tresponse></tresponse>统一建模,是否修改数据库由你决定;
  • MediatR本身不处理事务、缓存或事件发布,这些需你自行组合(比如配合Entity Framework Core + IUnitOfWork + IDomainEvent)。

二、快速上手:三步接入MediatR

以.NET 6+项目为例(控制台或Web API均可):

1. 安装包

通过NuGet安装:
MediatR(核心库)
MediatR.Extensions.Microsoft.DependencyInjection(集成ASP.NET Core DI)

2. 注册服务

Program.cs中添加:

builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(Program).Assembly));
登录后复制

这会自动扫描当前程序集下所有实现了IRequestHandlerINotificationHandler的类并注册。

3. 写一个查询示例

定义查询请求:

慧中标AI标书
慧中标AI标书

慧中标AI标书是一款AI智能辅助写标书工具。

慧中标AI标书 295
查看详情 慧中标AI标书
public record GetUserByIdQuery(int Id) : IRequest<UserDto>;
登录后复制

定义处理器:

public class GetUserByIdQueryHandler : IRequestHandler<GetUserByIdQuery, UserDto>
{
    private readonly IUserRepository _repo;
    public GetUserByIdQueryHandler(IUserRepository repo) => _repo = repo;

    public async Task<UserDto> Handle(GetUserByIdQuery request, CancellationToken ct)
        => await _repo.GetByIdAsync(request.Id, ct);
}
登录后复制

在Controller中使用:

[HttpGet("{id}")]
public async Task<ActionResult<UserDto>> Get(int id)
    => Ok(await _mediator.Send(new GetUserByIdQuery(id)));
登录后复制

三、命令与验证的最佳实践

命令通常伴随业务规则校验。推荐组合FluentValidation:

  • 为每个命令定义对应Validator(如CreateUserCommandValidator : AbstractValidator<createusercommand></createusercommand>);
  • 安装MediatR.Extensions.FluentValidation.AspNetCore,自动启用验证管道行为;
  • 验证失败时直接返回ValidationException,可在全局Filter中统一转为400响应。

命令执行后若需通知其他模块(如发邮件、更新搜索索引),不要在Handler里硬编码调用。改用INotification + INotificationHandler解耦:

await _mediator.Publish(new UserCreatedNotification(user), ct);
登录后复制

多个Handler可同时监听该事件,互不影响。

四、常见陷阱与应对建议

别把MediatR当Service Locator用:避免在Handler里通过IMediator再发另一个请求——这容易导致隐式调用链、事务边界混乱、难以调试。需要组合逻辑?提取成领域服务,由Handler协调。

事务控制要明确:MediatR不管理事务。命令Handler中若涉及EF Core操作,应在最外层(如中间件或基类Handler)开启DbContextTransaction,或用IUnitOfWork封装。

查询不要偷偷改状态:虽然技术上可以,但违背CQRS语义。如果某个“查询”必须触发副作用(如记录访问日志),应显式命名为TrackUserViewQuery,并在文档/命名中体现其非纯查询性质。

异步要到底:所有Handler方法必须标记async Task<t></t>,不要用.Result.Wait()阻塞——尤其在Web环境下会导致线程饥饿。

基本上就这些。MediatR本身很薄,真正考验的是你对领域边界的划分能力。用好它,不是为了炫技,而是让每个类只做一件事:接收请求、专注逻辑、返回结果。

以上就是C#如何实现CQRS模式 MediatR库入门与实践指南的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号