文章目录
- 项目地址
- 一、
-
- [1. 重点](#1. 重点)
-
- [1.1 Repository数据库接口](#1.1 Repository数据库接口)
- [1.2 GetEventDetail 完整的Query流程](#1.2 GetEventDetail 完整的Query流程)
- [1.3 创建CreateEventCommand并使用validation](#1.3 创建CreateEventCommand并使用validation)
项目地址
-
教程作者:ASP.NET Core Clean Architecture 2022-12
-
教程地址:
-
代码仓库地址:
- 所用到的框架和插件:
一、
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
- 设置验证类
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));
}
}
}
- 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}";
}
}
}
CreateEventCommandHandler.cs
:处理Command,并且使用validator

- 自定义验证逻辑:查询在
IEventRepository
接口里