前言
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
https://github.com/hueifeng/BlogSample/tree/master/src/CQRSMediatR