ASP.NET Core Clean Architecture


文章目录

  • 项目地址
  • 一、
    • [1. 重点](#1. 重点)
      • [1.1 Repository数据库接口](#1.1 Repository数据库接口)
      • [1.2 GetEventDetail 完整的Query流程](#1.2 GetEventDetail 完整的Query流程)
      • [1.3 创建CreateEventCommand并使用validation](#1.3 创建CreateEventCommand并使用validation)

项目地址

复制代码
  • 所用到的框架和插件:
复制代码

一、

1. 重点

1.1 Repository数据库接口

  • Application层的Contracts里的Persistence,存放数据库的接口
  • IAsyncRepository:基类主要功能,规定 增删改查/单一查询/分页
cs 复制代码
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 方法
cs 复制代码
namespace GloboTicket.TicketManagement.Application.Contracts.Persistence
{
    public interface ICategoryRepository : IAsyncRepository<Category>
    {
        Task<List<Category>> GetCategoriesWithEvents(bool includePassedEvents);
    }
}
  • IEventRepository.cs:添加Event自己的方法
cs 复制代码
namespace GloboTicket.TicketManagement.Application.Contracts.Persistence
{
    public interface IEventRepository : IAsyncRepository<Event>
    {
        Task<bool> IsEventNameAndDateUnique(string name, DateTime eventDate);
    }
}
  • IOrderRepository.cs: 没有自己的方法,直接继承使用
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的结构类似于
json 复制代码
{
    "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
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
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接口里
相关推荐
VX:Fegn08951 小时前
计算机毕业设计|基于ssm + vue超市管理系统(源码+数据库+文档)
前端·数据库·vue.js·spring boot·后端·课程设计
chipsense1 小时前
电流传感器型号从数据库查询并排序输出到网页的方法
数据库·php·传感器·霍尔电流传感器
踢足球09291 小时前
寒假打卡:2026-01-28
数据库·oracle
麦聪聊数据1 小时前
智慧医疗数据互联互通:使用 QuickAPI 构建实时诊疗数据交换层
数据库·sql·安全
风吹落叶花飘荡1 小时前
2026年mysql数据库迁移(全流程)
数据库·mysql
徐徐同学1 小时前
cpolar为IT-Tools 解锁公网访问,远程开发再也不卡壳
java·开发语言·分布式
2301_822382761 小时前
Python上下文管理器(with语句)的原理与实践
jvm·数据库·python
m0_748229991 小时前
Laravel8.X核心功能全解析
开发语言·数据库·php
Mr.朱鹏2 小时前
Nginx路由转发案例实战
java·运维·spring boot·nginx·spring·intellij-idea·jetty
液态不合群2 小时前
【面试题】MySQL 的索引下推是什么?
数据库·mysql