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

ASP.NET Core Clean Architecture


文章目录

  • 项目地址
  • 一、项目主体
    • 1. CQRS
      • 1.1 Repository数据库接口
      • 1.2 GetEventDetail 完整的Query流程
      • 1.3 创建CreateEventCommand并使用validation
    • 2. EFcore层
      • 2.1 BaseRepository
      • 2.2 CategoryRepository
      • 2.3 OrderRepository
    • 3. Email/Excel导出
      • 3.1 Email
        • 1. Email接口层
    • 4. 定义response
    • 5. JWT token
    • 6. 添加日志
    • 7. 版本控制
    • 8. 分页
    • 二、测试
      • 1. Unitest
      • 2. Integration Tests


项目地址

  • 教程作者:ASP.NET Core Clean Architecture 2022-12

  • 教程地址:

https://www.bilibili.com/video/BV1YZ421M7UA?spm_id_from=333.788.player.switch&vd_source=d14620e2c9f01dee5d2a104075027ad1&p=16
  • 代码仓库地址:
  • 所用到的框架和插件:

一、项目主体

  • Application层
    在这里插入图片描述

1. CQRS

1.1 Repository数据库接口

  • Application层的Contracts里的Persistence,存放数据库的接口
    在这里插入图片描述
  • IAsyncRepository:基类主要功能,规定 增删改查/单一查询/分页
namespace GloboTicket.TicketManagement.Application.Contracts.Persistence
{public interface IAsyncRepository<T> where T : class{Task<T?> GetByIdAsync(Guid id);Task<IReadOnlyList<T>> ListAllAsync();Task<T> AddAsync(T entity);Task UpdateAsync(T entity);Task DeleteAsync(T entity);Task<IReadOnlyList<T>> GetPagedReponseAsync(int page, int size);}
}
  • ICategoryRepository.cs:添加自己独特的GetCategoriesWithEvents 方法
namespace GloboTicket.TicketManagement.Application.Contracts.Persistence
{public interface ICategoryRepository : IAsyncRepository<Category>{Task<List<Category>> GetCategoriesWithEvents(bool includePassedEvents);}
}
  • IEventRepository.cs:添加Event自己的方法
namespace GloboTicket.TicketManagement.Application.Contracts.Persistence
{public interface IEventRepository : IAsyncRepository<Event>{Task<bool> IsEventNameAndDateUnique(string name, DateTime eventDate);}
}
  • IOrderRepository.cs: 没有自己的方法,直接继承使用
namespace GloboTicket.TicketManagement.Application.Contracts.Persistence
{public interface IOrderRepository: IAsyncRepository<Order>{}
}

1.2 GetEventDetail 完整的Query流程

  • 项目层级
    在这里插入图片描述

  • EventDetailVm.cs :用于返回给接口的数据

在这里插入图片描述

  • CategoryDto.cs:表示在GetEventDetail里需要用到的Dto
    在这里插入图片描述
  • GetEventDetailQuery.cs :传入ID的值,以及返回EventDetailVm

在这里插入图片描述

  • GetEventDetailQueryHandler.cs :返回查询

在这里插入图片描述

  • 返回API的结构类似于
{"eventId": "123e4567-e89b-12d3-a456-426614174000","name": "Rock Concert","price": 100,"artist": "The Rock Band","date": "2023-12-25T20:00:00","description": "An amazing rock concert to end the year!","imageUrl": "https://example.com/images/rock-concert.jpg","categoryId": "456e7890-f12g-34h5-i678-901234567890","category": {"id": "456e7890-f12g-34h5-i678-901234567890","name": "Music"}
}

1.3 创建CreateEventCommand并使用validation

  1. 设置验证类 CreateEventCommandValidator.cs
using FluentValidation;
using GloboTicket.TicketManagement.Application.Contracts.Persistence;
using System;
using System.Threading;
using System.Threading.Tasks;namespace GloboTicket.TicketManagement.Application.Features.Events.Commands.CreateEvent
{public class CreateEventCommandValidator : AbstractValidator<CreateEventCommand>{private readonly IEventRepository _eventRepository;public CreateEventCommandValidator(IEventRepository eventRepository){_eventRepository = eventRepository;RuleFor(p => p.Name).NotEmpty().WithMessage("{PropertyName} is required.").NotNull().MaximumLength(50).WithMessage("{PropertyName} must not exceed 50 characters.");RuleFor(p => p.Date).NotEmpty().WithMessage("{PropertyName} is required.").NotNull().GreaterThan(DateTime.Now);RuleFor(e => e).MustAsync(EventNameAndDateUnique).WithMessage("An event with the same name and date already exists.");RuleFor(p => p.Price).NotEmpty().WithMessage("{PropertyName} is required.").GreaterThan(0);}private async Task<bool> EventNameAndDateUnique(CreateEventCommand e, CancellationToken token){return !(await _eventRepository.IsEventNameAndDateUnique(e.Name, e.Date));}}
}
  1. Command类:CreateEventCommand.cs
using MediatR;namespace GloboTicket.TicketManagement.Application.Features.Events.Commands.CreateEvent
{public class CreateEventCommand: IRequest<Guid>{public string Name { get; set; } = string.Empty;public int Price { get; set; }public string? Artist { get; set; }public DateTime Date { get; set; }public string? Description { get; set; }public string? ImageUrl { get; set; }public Guid CategoryId { get; set; }public override string ToString(){return $"Event name: {Name}; Price: {Price}; By: {Artist}; On: {Date.ToShortDateString()}; Description: {Description}";}}
}
  1. CreateEventCommandHandler.cs:处理Command,并且使用validator

在这里插入图片描述

  1. 自定义验证逻辑:查询在IEventRepository接口里
    在这里插入图片描述

2. EFcore层

  • 数据库接口层:Core层的Contracts里的Persistence
    在这里插入图片描述

  • 实现层:Infrastructure层的Persistence
    在这里插入图片描述

2.1 BaseRepository

  • BaseRepository.cs:定义
    在这里插入图片描述

2.2 CategoryRepository

  • CategoryRepository.cs:继承BaseRepository,以及实现接口
    在这里插入图片描述

2.3 OrderRepository

  • OrderRepository.cs 使用分页
    在这里插入图片描述

3. Email/Excel导出

3.1 Email

1. Email接口层
  • Core层的Infrastructure

4. 定义response

5. JWT token

6. 添加日志

7. 版本控制

8. 分页

二、测试

  • 使用框架
Moq用来模拟数据
Shouldly 用来断言
xunit 测试框架

1. Unitest

  • Automatically 代码片段测试,快速
  • 测试的是Public API
  • 独立运行 run in isolation
  • 结果断言

2. Integration Tests

  • end to end test between different layers
  • more work to set up
  • often linked with database

http://www.mrgr.cn/news/92018.html

相关文章:

  • Spring Boot 概要(官网文档解读)
  • 我们来学人工智能 -- DeepSeek客户端
  • FPGA DSP:Vivado 中带有 DDS 的 FIR 滤波器
  • 高等数学(上)题型笔记(六)定积分的应用
  • 从零开始用react + tailwindcs + express + mongodb实现一个聊天程序(一)
  • Linux-Ansible模块进阶
  • Windows本地安装ComfyUI
  • 大数据之常用Linux操作
  • 在windows下安装windows+Ubuntu16.04双系统(下)
  • langchain系列 - FewShotPromptTemplate 少量示例
  • 【论文带读(1)】《End-to-End Object Detection with Transformers》论文超详细带读 + 翻译
  • 出行项目案例
  • 1.15作业
  • 基于Flink SQL实现7天用户行为风险识别,结合滚动窗口预聚合与CEP复杂事件处理技术,根据用户7天的动作,包括交易,支付,评价等行为,识别用户的风险等级
  • 【找工作】C++和算法复习(自用)
  • Golang | 每日一练 (3)
  • Oracle备库srvctl start丢失某个原有的service_names的案例
  • C/C++跳动的爱心
  • AD(Altium Designer)器件封装——立创商城导出原理图和PCB完成器件封装操作指南
  • 如何用校园内网远程连接服务器