当前位置: 首页 > web >正文

(二)毛子整洁架构(CQRS/Dapper/DomianEvent Handler)


文章目录

  • 项目地址
  • 一、Application 层
    • 1.1 定义CQRS的接口以及其他服务
      • 1. Command
      • 2. IQuery查询
      • 3. 当前时间服务接口
      • 4. 邮件发送服务接口
    • 1.2 ReserveBooking Command
      • 1. 处理传入的参数
      • 2. ReserveBookingCommandHandler
      • 3. BookingReservedDomainEvent
    • 1.3 GetBooking Query
      • 1. 创建Dapper的链接接口


项目地址

  • 教程作者:
  • 教程地址:
  • 代码仓库地址:
  • 所用到的框架和插件:
dbt 
airflow

一、Application 层

1.1 定义CQRS的接口以及其他服务

在这里插入图片描述

1. Command

  • 用于处理除查询以外的
  1. ICommand.cs
using Bookify.Domain.Abstractions;
using MediatR;
namespace Bookify.Application.Abstractions.Messaging;
//无返回值的命令
public interface ICommand : IRequest<Result>
{
}
//返回一个TReponse的命令
public interface ICommand<TReponse> : IRequest<Result<TReponse>>
{
}
  1. ICommandHandler.cs
namespace Bookify.Application.Abstractions.Messaging;
public interface ICommandHandler<TCommand> : IRequestHandler<TCommand, Result>where TCommand : ICommand
{
}public interface ICommandHandler<TCommand, TResponse> : IRequestHandler<TCommand, Result<TResponse>>where TCommand : ICommand<TResponse>
{
}

2. IQuery查询

  • 用于查询
    IQuery.cs
using Bookify.Domain.Abstractions;
using MediatR;
namespace Bookify.Application.Abstractions.Messaging;
public interface IQuery<TResponse> : IRequest<Result<TResponse>>
{
}
  • IQueryHandler.cs
using Bookify.Domain.Abstractions;
using MediatR;
namespace Bookify.Application.Abstractions.Messaging;
public interface IQueryHandler<TQuery, TResponse> : IRequestHandler<TQuery, Result<TResponse>>where TQuery : IQuery<TResponse>
{
}

3. 当前时间服务接口

  • 用于提供当前时间
namespace Bookify.Application.Abstractions.Clock;public interface IDateTimeProvider
{DateTime UtcNow { get; }
}

4. 邮件发送服务接口

  • 发送邮件的服务
namespace Bookify.Application.Abstractions.Email;
public interface IEmailService
{Task SendAsync(Domain.Users.Email recipient, string subject, string body);
}

1.2 ReserveBooking Command

在这里插入图片描述

1. 处理传入的参数

  • ReserveBookingCommand.cs:返回值是Guid,参数时4个
using Bookify.Application.Abstractions.Messaging;
namespace Bookify.Application.Bookings.ReserveBooking;
public record ReserveBookingCommand(Guid ApartmentId,Guid UserId,DateOnly StartDate,DateOnly EndDate) : ICommand<Guid>;

2. ReserveBookingCommandHandler

  • 用于保存预定的处理方法
internal sealed class ReserveBookingCommandHandler : ICommandHandler<ReserveBookingCommand, Guid>
{private readonly IUserRepository _userRepository;private readonly IApartmentRepository _apartmentRepository;private readonly IBookingRepository _bookingRepository;private readonly IUnitOfWork _unitOfWork;private readonly PricingService _pricingService;private readonly IDateTimeProvider _dateTimeProvider;public ReserveBookingCommandHandler(IUserRepository userRepository,IApartmentRepository apartmentRepository,IBookingRepository bookingRepository,IUnitOfWork unitOfWork,PricingService pricingService,IDateTimeProvider dateTimeProvider){_userRepository = userRepository;_apartmentRepository = apartmentRepository;_bookingRepository = bookingRepository;_unitOfWork = unitOfWork;_pricingService = pricingService;_dateTimeProvider = dateTimeProvider;}public async Task<Result<Guid>> Handle(ReserveBookingCommand request, CancellationToken cancellationToken){// Check if the user existsUser? user = await _userRepository.GetByIdAsync(request.UserId, cancellationToken);if (user is null){return Result.Failure<Guid>(UserErrors.NotFound);}// Check if the apartment existsApartment? apartment = await _apartmentRepository.GetByIdAsync(request.ApartmentId, cancellationToken);if (apartment is null){return Result.Failure<Guid>(ApartmentErrors.NotFound);}//创建预定时间段var duration = DateRange.Create(request.StartDate, request.EndDate);// Check if the booking duration is validif (await _bookingRepository.IsOverlappingAsync(apartment, duration, cancellationToken)){return Result.Failure<Guid>(BookingErrors.Overlap);}var booking = Booking.Reserve(apartment,user.Id,duration,_dateTimeProvider.UtcNow,_pricingService);//添加booking_bookingRepository.Add(booking);//保存await _unitOfWork.SaveChangesAsync(cancellationToken);return booking.Id;}
}

3. BookingReservedDomainEvent

  • 处理 BookingReservedDomainEvent 事件的逻辑,这里只是一个处理的函数,并没有自动执行,只有当发布了事件之后,才会触发
namespace Bookify.Application.Bookings.ReserveBooking;/// 处理 BookingReservedDomainEvent 事件
internal sealed class BookingReservedDomainEventHandler : INotificationHandler<BookingReservedDomainEvent>
{private readonly IBookingRepository _bookingRepository;private readonly IUserRepository _userRepository;private readonly IEmailService _emailService;public BookingReservedDomainEventHandler(IEmailService emailService, IUserRepository userRepository, IBookingRepository bookingRepository){_emailService = emailService;_userRepository = userRepository;_bookingRepository = bookingRepository;}public async Task Handle(BookingReservedDomainEvent notification, CancellationToken cancellationToken){//通过事件里传来的 BookingId 从数据库查出预订信息。Booking? booking = await _bookingRepository.GetByIdAsync(notification.BookingId, cancellationToken);if (booking is null){return;}//根据 booking.UserId 查出用户信息。User? user = await _userRepository.GetByIdAsync(booking.UserId, cancellationToken);if (user is null){return;}//通过用户信息发送邮件。await _emailService.SendAsync(user.Email,"Booking reserved!","You have 10 minutes to confirm this booking");}
}

1.3 GetBooking Query

  • 所有查询,直接使用Dapper

1. 创建Dapper的链接接口

http://www.xdnf.cn/news/4207.html

相关文章:

  • 高效调用京东 API 实战:商品详情页实时数据采集接口开发指南​
  • C++ this关键字
  • python校园二手交易管理系统-闲置物品交易系统
  • ts axios中报 Property ‘code‘ does not exist on type ‘AxiosResponse<any, any>‘
  • PCIe控制逻辑介绍(一)
  • 【C/C++】new关键字解析
  • 说下RabbitMQ的整体架构
  • K-means
  • 一款独立于游戏外的键盘源按键辅助工具他来了
  • C#发送之前转换为JSON格式
  • 美妆集合体验馆的「AI 焕新」:从人工到智能管理的蜕变
  • FPGA设计如何快速入门?(内附学习视频)
  • Kotlin Lambda优化Android事件处理
  • 极端工况的高频电流探头精度优化
  • Python实例题:Python操作excel自动化开发
  • 6.5 行业特定应用:金融、医疗、制造等行业的定制化解决方案
  • 数据结构 --- 栈
  • 基于RT-Thread的STM32F4开发第二讲第一篇——ADC
  • Flutter 布局
  • dubbo限流
  • Android OKHttp原理简单说明
  • 怎样通过API 实现python调用Chatgpt,gemini
  • 俄罗斯电商市场:增长与变革中的新势力崛起
  • 理解IP四元组与网络五元组:网络流量的“身份证”
  • vue+tsc+noEmit导致打包报TS类型错误问题及解决方法
  • 如何解决Kafka集群中Broker磁盘IO瓶颈?
  • ActiveMQ 安全机制与企业级实践(一)
  • Leetcode Hot 100最长连续序列
  • MongoDB常用操作示例
  • vue3+ts学习!