.NET Core 使用MediatR CQRS模式

前言

CQRS(Command Query Responsibility Segregation)命令查詢職責分離模式,它主要從我們業務系統中進行分離出我們(Command 增、刪、改)和(Query 查),
同時他可以明確的區分我們每一個動作向我們的請求模型和響應模型.從而降低了我們系統的複雜性.

CQRS模式通過使用不同的介面來分離讀取數據和更新數據的操作。CQRS模式可以最大化性能,擴展性以及安全性, 還會為系統的持續演化提供更多的彈性,防止Update命令在域模型Level發生衝突。
通常情況我們使用同一數據模型進行我們數據的查詢和修改,這是一個非常簡單的CURD,在一些複雜的應用程式中,這種方法會變的難以操作,例如在讀取方面應用程式可能會存在大量的查詢,
返回具有不同的數據傳輸對象(DTO),對象映射可能會變的非常複雜,在寫入方面,模型可能實施複雜的驗證和業務邏輯.結果導致模型太多操作,整體變的相當得複雜.

如下圖所示:

MediatR他為我們解決將消息發送與消息處理進行了解耦,他同時支援非同步和同步來發送和監聽消息.

MediatR

Install MediatR

PM> Install-Package MediatR
  • IMeditator
  • IRequese、IRequest
  • IRequestHandler<in TRequest, TResponse>
    public class CreateOrderRequestModel: 
        IRequest<string>
    {
        public string UserId { get; set; }
        public string CardNumber { get; set; }
    }
    public class GetOrderByIdRequestModel:IRequest<string>
    {
        public string OrderId { get; set; }
    }
 //返回值
 public interface IRequest<out TResponse> : IBaseRequest{}
 //無返回值
 public interface IRequest : IRequest<Unit>, IBaseRequest{}

創建處理程式,所有的處理程式都通過IRequestHandler介面來實現,該介面有兩個參數,第一個是請求內容,第二個是響應內容.

    public class CreateOrderCommandHandler
        : IRequestHandler<CreateOrderRequestModel, string>
    {
        public Task<string> Handle(CreateOrderRequestModel request, CancellationToken cancellationToken)
        {
            //do something...
            return Task.FromResult(request.UserId);
        }
    }

正如下程式碼片段,處理程式實現了IRequestHandler帶有輸入和輸出類型定義的介面

public interface IRequestHandler<in TRequest, TResponse> where TRequest : IRequest<TResponse>
  {
    Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken);
  }
    public class GetOrderByIdQueryHandler :
        IRequestHandler<GetOrderByIdRequestModel, string>
    {
        public Task<string> Handle(GetOrderByIdRequestModel request, CancellationToken cancellationToken)
        {
            //do something
            return Task.FromResult(request.OrderId);
        }
    }

Install MediatR.Extensions.Microsoft.DependencyInjection

PM> MediatR.Extensions.Microsoft.DependencyInjection

在Startup.cs中註冊MediatR

services.AddMediatR(Assembly.GetExecutingAssembly());

我們只需要注入IMediator介面,通過如下程式碼我們來使用他們

    [Route("api/[controller]")]
    [ApiController]
    public class OrderController : ControllerBase
    {
        private readonly IMediator _mediator;
        public OrderController(IMediator mediator)
        {
            _mediator = mediator;
        }

        [HttpPost]
        public async Task<IActionResult> Post([FromBody]CreateOrderRequestModel requestModel)
        {
            var response =await _mediator.Send(requestModel);
            return Ok(response);
        }

        [HttpGet]
        public async Task<IActionResult> Get([FromQuery]GetOrderByIdRequestModel requestModel)
        {
            var response = await _mediator.Send(requestModel);
            return Ok(response);
        }
    }

CQRS 主要包含兩大概念,一個是讀寫分離,一個是事件源。事件源不是必須項

Reference

//github.com/hueifeng/BlogSample/tree/master/src/CQRSMediatR