ABP - CRUD 增删改查 [IRepository、AbstractCrudAppService、AbstractKeyCrudAppService、PagedAndSortedResultRequestDto]

一、CRUD 增删改查

核心辅助类

  • 基于IRepository的方法:InsertAsyncUpdateAsyncDeleteAsyncGetAsync等。
  • AbstractCrudAppService<TEntity, TDto, TKey>:基于主键的 CRUD 抽象服务,自动实现GetGetListCreateUpdateDelete等基础方法。
  • AbstractKeyCrudAppService<TEntity, TDto, TKey, TGetListInput, TCreateInput, TUpdateInput>:更灵活的泛型 CRUD 基类,支持自定义输入 DTO(适用于复杂查询 / 创建 / 更新场景)。
  • PagedAndSortedResultRequestDto:分页和排序的基础输入 DTO(配合 CRUD 服务实现分页查询)。

你关注的这几个类是ABP框架实现快速CRUD开发的核心工具,从仓储层的基础操作到服务层的自动化接口,能大幅减少重复代码。下面通过完整示例,带你理解它们的联动用法和设计逻辑:

1. 基于 IRepository 的基础CRUD方法

IRepository是ABP仓储层的通用接口,封装了实体的基础CRUD操作(InsertAsync/UpdateAsync等),无需手动编写SQL或ORM语句,框架会自动适配底层ORM(如EF Core、SqlSugar)。

示例:在服务中使用IRepository

using Volo.Abp.Domain.Repositories;
using Volo.Abp.Application.Services;

// 1. 定义实体(Book)
public class Book : Entity<Guid>
{
    public string Name { get; set; }
    public decimal Price { get; set; }
    public DateTime CreationTime { get; set; } = DateTime.Now;
}

// 2. 定义DTO(数据传输对象,避免直接暴露实体)
public class BookDto : EntityDto<Guid>
{
    public string Name { get; set; }
    public decimal Price { get; set; }
}

// 3. 应用服务(手动实现CRUD,依赖IRepository)
public class BookAppService : ApplicationService
{
    private readonly IRepository<Book, Guid> _bookRepository;

    // 注入IRepository<Book, Guid>
    public BookAppService(IRepository<Book, Guid> bookRepository)
    {
        _bookRepository = bookRepository;
    }

    // 新增:使用InsertAsync
    public async Task<BookDto> CreateAsync(BookDto input)
    {
        // 实体映射(DTO -> 实体)
        var book = ObjectMapper.Map<BookDto, Book>(input);
        // 仓储新增:返回新增后的实体(含ID)
        var newBook = await _bookRepository.InsertAsync(book);
        // 实体 -> DTO 返回
        return ObjectMapper.Map<Book, BookDto>(newBook);
    }

    // 单查:使用GetAsync
    public async Task<BookDto> GetAsync(Guid id)
    {
        var book = await _bookRepository.GetAsync(id);
        return ObjectMapper.Map<Book, BookDto>(book);
    }

    // 列表查询:使用GetListAsync(带条件)
    public async Task<List<BookDto>> GetListAsync(string bookName)
    {
        // 带过滤条件的查询
        var books = await _bookRepository.GetListAsync(
            book => book.Name.Contains(bookName) // Lambda条件
        );
        return ObjectMapper.Map<List<Book>, List<BookDto>>(books);
    }

    // 更新:使用UpdateAsync
    public async Task<BookDto> UpdateAsync(Guid id, BookDto input)
    {
        // 先查询实体
        var book = await _bookRepository.GetAsync(id);
        // 赋值更新
        ObjectMapper.Map(input, book);
        // 仓储更新
        var updatedBook = await _bookRepository.UpdateAsync(book);
        return ObjectMapper.Map<Book, BookDto>(updatedBook);
    }

    // 删除:使用DeleteAsync
    public async Task DeleteAsync(Guid id)
    {
        await _bookRepository.DeleteAsync(id);
    }
}

讲解:

  • 核心方法作用:
    • InsertAsync:新增实体,自动赋值主键(如Guid自增、雪花ID),返回新增后的实体。
    • GetAsync:根据主键查询单个实体,不存在时抛EntityNotFoundException
    • GetListAsync:支持Lambda条件查询,返回符合条件的实体列表。
    • UpdateAsync:更新实体(需先查询出实体再赋值),返回更新后的实体。
    • DeleteAsync:根据主键删除实体,支持批量删除(DeleteAsync(book => book.Price < 0))。
  • 依赖ORMIRepository的实现由底层ORM决定(如EF Core用EfCoreRepository,SqlSugar用SqlSugarRepository),开发者无需关心ORM细节。

2. AbstractCrudAppService:简化CRUD服务(基础版)

AbstractCrudAppService是ABP服务层的抽象基类,自动实现Get/GetList/Create/Update/Delete等基础方法,无需手动编写上述BookAppService中的重复逻辑。

示例:继承AbstractCrudAppService

using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;

// 1. 复用上面的Book实体和BookDto

// 2. 继承AbstractCrudAppService,自动获得基础CRUD方法
public class BookCrudAppService : AbstractCrudAppService<
    Book,               // 实体类型
    BookDto,            // 返回DTO类型
    Guid,               // 实体主键类型
    PagedAndSortedResultRequestDto, // 列表查询输入DTO(分页排序)
    BookDto,            // 创建输入DTO(直接复用返回DTO)
    BookDto             // 更新输入DTO(直接复用返回DTO)
>
{
    // 构造函数:注入仓储,调用父类构造
    public BookCrudAppService(IRepository<Book, Guid> repository) 
        : base(repository)
    {
        // 可选:配置权限(如只有Admin能删除)
        GetPolicyName = "BookManagement.Read";
        DeletePolicyName = "BookManagement.Delete";
    }

    // 可选:重写方法自定义逻辑(如新增时补充创建人)
    protected override async Task<Book> MapToEntityAsync(BookDto createInput, Book entity)
    {
        var book = await base.MapToEntityAsync(createInput, entity);
        // 补充当前用户ID(需注入ICurrentUser)
        book.CreatorId = CurrentUser.Id; 
        return book;
    }
}

讲解:

  • 自动生成的方法:继承后无需编写代码,框架自动暴露以下API(配合动态API):
    • GET /api/app/book/{id}:单查(对应GetAsync)。
    • GET /api/app/book:分页列表(对应GetListAsync,支持Skip/Take/Sorting)。
    • POST /api/app/book:新增(对应CreateAsync)。
    • PUT /api/app/book/{id}:更新(对应UpdateAsync)。
    • DELETE /api/app/book/{id}:删除(对应DeleteAsync)。
  • 自定义扩展:通过重写父类方法(如MapToEntityAsyncMapToDtoAsync)添加业务逻辑,不破坏自动实现的基础功能。
  • 权限集成:通过GetPolicyName/CreatePolicyName等属性绑定权限,实现接口授权(需配合ABP权限系统)。

3. AbstractKeyCrudAppService:灵活CRUD服务(复杂版)

AbstractKeyCrudAppServiceAbstractCrudAppService的泛型扩展,支持自定义输入DTO,适用于查询/创建/更新逻辑复杂的场景(如查询需多条件过滤、创建需特殊字段验证)。

示例:继承AbstractKeyCrudAppService

using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;

// 1. 定义自定义输入DTO(复杂查询/创建/更新)
// 列表查询输入:支持书名模糊查询+分页+排序
public class GetBookListInput : PagedAndSortedResultRequestDto
{
    public string BookName { get; set; } // 新增自定义查询条件
    public decimal? MinPrice { get; set; } // 新增价格下限过滤
}

// 创建输入:仅允许传递Name和Price,且Name必填
public class CreateBookInput
{
    [Required] // 验证特性
    public string Name { get; set; }
    public decimal Price { get; set; }
}

// 更新输入:允许部分字段更新(如只更新Price)
public class UpdateBookInput
{
    public decimal? Price { get; set; } // 可选字段,支持部分更新
}

// 2. 继承AbstractKeyCrudAppService,使用自定义DTO
public class BookAdvancedCrudAppService : AbstractKeyCrudAppService<
    Book,               // 实体类型
    BookDto,            // 返回DTO类型
    Guid,               // 主键类型
    GetBookListInput,   // 自定义列表查询输入
    CreateBookInput,    // 自定义创建输入
    UpdateBookInput     // 自定义更新输入
>
{
    public BookAdvancedCrudAppService(IRepository<Book, Guid> repository) 
        : base(repository)
    {
    }

    // 重写列表查询:添加自定义过滤条件(BookName+MinPrice)
    protected override async Task<IQueryable<Book>> CreateFilteredQueryAsync(GetBookListInput input)
    {
        var query = await base.CreateFilteredQueryAsync(input);

        // 过滤1:书名模糊查询(输入不为空时)
        if (!string.IsNullOrWhiteSpace(input.BookName))
        {
            query = query.Where(book => book.Name.Contains(input.BookName));
        }

        // 过滤2:价格下限(输入不为空时)
        if (input.MinPrice.HasValue)
        {
            query = query.Where(book => book.Price >= input.MinPrice.Value);
        }

        return query;
    }

    // 重写更新:支持部分字段更新(只更新有值的字段)
    protected override async Task MapToEntityAsync(UpdateBookInput updateInput, Book entity)
    {
        // 仅更新Price(如果输入有值)
        if (updateInput.Price.HasValue)
        {
            entity.Price = updateInput.Price.Value;
        }
        // 其他字段不更新(如Name保持不变)
    }
}

讲解:

  • 自定义输入DTO优势:
    • 查询输入(GetBookListInput):在分页排序基础上添加业务字段(如BookName),满足复杂查询需求。
    • 创建输入(CreateBookInput):仅暴露必要字段,配合[Required]等验证特性,确保输入合法性。
    • 更新输入(UpdateBookInput):支持部分字段更新(如只改价格),避免全量赋值。
  • 核心重写方法:
    • CreateFilteredQueryAsync:重写列表查询的过滤逻辑,添加自定义条件。
    • MapToEntityAsync:重写DTO到实体的映射,支持部分更新或特殊字段处理。
  • 自动化仍保留:即使自定义输入,Get/Create/Update等方法的核心逻辑(如仓储调用、事务管理)仍由框架自动实现。

4. PagedAndSortedResultRequestDto:分页排序基础DTO

PagedAndSortedResultRequestDto是ABP提供的基础输入DTO,封装了分页Skip/Take)和排序Sorting)参数,直接用于CRUD服务的列表查询。

示例:使用PagedAndSortedResultRequestDto

// 1. 基础用法(直接作为输入DTO)
public class SimpleBookAppService : AbstractCrudAppService<
    Book, 
    BookDto, 
    Guid, 
    PagedAndSortedResultRequestDto // 直接使用基础分页DTO
>
{
    public SimpleBookAppService(IRepository<Book, Guid> repository) : base(repository)
    {
    }
}

// 2. 前端调用示例(传递分页排序参数)
// GET请求URL:/api/app/book?Skip=0&Take=10&Sorting=CreationTime%20desc
// - Skip=0:跳过0条(第一页)
// - Take=10:取10条(每页10条)
// - Sorting=CreationTime desc:按CreationTime降序排序

// 3. 自定义分页DTO(继承扩展)
public class GetBookWithAuthorInput : PagedAndSortedResultRequestDto
{
    public Guid? AuthorId { get; set; } // 扩展:按作者ID过滤
}

讲解:

  • 核心属性:
    • Skip:跳过的记录数(计算页码:Skip = (页码-1)*Take)。
    • Take:获取的记录数(每页条数)。
    • Sorting:排序规则(格式:字段名 [asc|desc],如Name ascPrice desc)。
  • 扩展性:通过继承PagedAndSortedResultRequestDto添加自定义字段(如AuthorId),实现“分页+排序+业务过滤”的组合查询。
  • 自动支持:ABP的AbstractCrudAppService会自动解析PagedAndSortedResultRequestDto的参数,无需手动处理分页和排序逻辑。

核心总结:CRUD工具的选择逻辑

工具类 适用场景 优势
IRepository 自定义CRUD逻辑、复杂业务 灵活性高,支持全自定义
AbstractCrudAppService 简单CRUD场景(输入输出DTO一致) 零代码实现基础CRUD,开发效率高
AbstractKeyCrudAppService 复杂场景(自定义查询/创建/更新输入) 兼顾自动化和灵活性,支持部分更新
PagedAndSortedResultRequestDto 所有列表查询场景 标准化分页排序参数,减少重复DTO定义

要不要我帮你整理一份ABP CRUD服务的完整代码模板?包含实体、DTO、仓储、服务的联动代码,你可以直接替换业务字段复用。

二、ABP框架 CRUD增删改查 核心类与辅助类全解析

以下内容聚焦CRUD场景,从“仓储层操作类→服务层封装类→DTO传输类→扩展辅助类”四个维度,完整梳理核心类、辅助类及关联功能,覆盖基础到进阶的全场景用法:

一、仓储层核心类(数据访问基础)

仓储层是CRUD的底层支撑,负责与数据库交互,ABP提供通用接口与ORM实现类,无需手动写SQL:

1. 通用仓储接口(IRepository系列)

类/接口 核心作用 关键方法示例
IRepository<TEntity, TKey> 基础CRUD接口(全量操作) InsertAsync(新增)、GetAsync(单查)、UpdateAsync(更新)、DeleteAsync(删除)、GetListAsync(列表查询)
IReadOnlyRepository<TEntity, TKey> 只读仓储接口(无写入操作) GetAsyncGetListAsyncCountAsync(统计)、AnyAsync(存在性判断)、MaxAsync(最大值查询)
IQueryableRepository<TEntity, TKey> 支持IQueryable的仓储接口(复杂查询) WithDetailsAsync(关联查询)、AsQueryable(转为IQueryable)

示例:IQueryableRepository关联查询

// 注入支持关联查询的仓储
private readonly IQueryableRepository<Book, Guid> _bookRepo;

// 查书籍时关联查询作者(EF Core/SqlSugar通用)
public async Task<BookDto> GetWithAuthorAsync(Guid id)
{
    var book = await _bookRepo.WithDetailsAsync(b => b.Author) // 关联Author导航属性
                              .FirstOrDefaultAsync(b => b.Id == id);
    return ObjectMapper.Map<Book, BookDto>(book);
}

2. ORM实现类(仓储具体实现)

不同ORM对应不同的仓储实现类,ABP自动适配,开发者无需关心底层细节:

类名 适配ORM 核心特点
EfCoreRepository<TEntity, TKey> EF Core 支持EF Core的Include(关联)、ThenInclude(多级关联)、迁移自动生成
EfCoreRepositoryBase<TDbContext, TEntity, TKey> EF Core 支持多数据库上下文(多库场景),需指定TDbContext
SqlSugarRepository<TEntity, TKey> SqlSugar 支持SqlSugar的链式查询、批量操作、存储过程调用,性能更优
MongoDbRepository<TEntity, TKey> MongoDB 适配NoSQL数据库,支持文档型数据的CRUD,方法与关系型ORM保持一致

示例:多上下文EF Core仓储

// 自定义主库仓储(绑定MainDbContext)
public class BookMainRepo : EfCoreRepositoryBase<MainDbContext, Book, Guid>, IBookRepository
{
    public BookMainRepo(IDbContextProvider<MainDbContext> dbCtxProvider) : base(dbCtxProvider) { }
}

// 自定义日志库仓储(绑定LogDbContext)
public class BookLogRepo : EfCoreRepositoryBase<LogDbContext, BookOperateLog, Guid>, IBookLogRepository
{
    public BookLogRepo(IDbContextProvider<LogDbContext> dbCtxProvider) : base(dbCtxProvider) { }
}

二、服务层封装类(CRUD逻辑自动化)

服务层通过抽象基类封装重复CRUD逻辑,开发者只需关注业务差异,无需写基础接口:

1. 基础CRUD服务基类

类名 适用场景 核心优势
AbstractCrudAppService<TEntity, TDto, TKey> 简单CRUD(输入/输出DTO一致) 自动实现5个基础接口(Get/GetList/Create/Update/Delete),零代码快速开发
AbstractKeyCrudAppService<TEntity, TDto, TKey, TGetListInput, TCreateInput, TUpdateInput> 复杂CRUD(自定义输入DTO) 支持查询/创建/更新用不同DTO,适配多条件查询、部分字段更新等场景
CrudAppServiceBase<TEntity, TDto, TKey> 需完全自定义CRUD逻辑 仅提供基础依赖(仓储、对象映射),方法需手动实现,灵活性最高

示例:AbstractKeyCrudAppService完整用法

// 1. 自定义输入DTO(查询/创建/更新分离)
public class GetBookInput : PagedAndSortedResultRequestDto { public string? BookName { get; set; } }
public class CreateBookInput { [Required] public string Name { get; set; } public decimal Price { get; set; } }
public class UpdateBookInput { public decimal? Price { get; set; } } // 仅允许更新价格

// 2. 继承抽象服务类,自动生成CRUD接口
public class BookCrudService : AbstractKeyCrudAppService<
    Book,               // 实体
    BookDto,            // 返回DTO
    Guid,               // 主键
    GetBookInput,       // 查询输入
    CreateBookInput,    // 创建输入
    UpdateBookInput     // 更新输入
>
{
    // 注入仓储(父类需仓储构造参数)
    public BookCrudService(IRepository<Book, Guid> repo) : base(repo) 
    {
        // 配置权限(可选,关联ABP权限系统)
        CreatePolicyName = "Book.Create";
        DeletePolicyName = "Book.Delete";
    }

    // 重写查询过滤:添加书名模糊查询
    protected override async Task<IQueryable<Book>> CreateFilteredQueryAsync(GetBookInput input)
    {
        var query = await base.CreateFilteredQueryAsync(input);
        if (!string.IsNullOrWhiteSpace(input.BookName))
        {
            query = query.Where(b => b.Name.Contains(input.BookName));
        }
        return query;
    }

    // 重写更新逻辑:仅更新有值的字段
    protected override async Task MapToEntityAsync(UpdateBookInput input, Book entity)
    {
        if (input.Price.HasValue) entity.Price = input.Price.Value;
        // 其他字段不更新(如Name不可修改)
    }
}

2. 服务层辅助类

类名 核心作用 示例用法
IObjectMapper DTO与实体的映射(自动映射) ObjectMapper.Map<Book, BookDto>(book)(实体转DTO)
ICurrentUser 获取当前用户信息(CRUD时记录操作人) entity.CreatorId = CurrentUser.Id;(新增时记录创建人)
IUnitOfWorkManager 手动管理事务(多CRUD操作原子性) using (var uow = _uowManager.Begin()) { /* 多步CRUD */ uow.Complete(); }

三、DTO传输类(数据交互规范)

DTO用于隔离实体与接口,定义CRUD的数据传输格式,ABP提供标准化基类:

1. 基础DTO基类

类名 适用场景 核心属性
EntityDto<TKey> 基础返回DTO(带主键) Id(主键)
CreationAuditedEntityDto<TKey> 带创建审计的返回DTO IdCreationTime(创建时间)、CreatorId(创建人ID)
AuditedEntityDto<TKey> 带全审计的返回DTO(创建+修改) 继承CreationAuditedEntityDto,增加LastModificationTimeLastModifierId
FullAuditedEntityDto<TKey> 带软删除审计的返回DTO 继承AuditedEntityDto,增加IsDeleted(软删除标记)、DeletionTime

2. 查询/分页DTO基类

类名 适用场景 核心属性
PagedAndSortedResultRequestDto 基础分页排序查询输入 Skip(跳过条数)、Take(获取条数)、Sorting(排序规则,如“Name asc”)
PagedResultDto<TDto> 分页查询结果返回 TotalCount(总条数)、Items(当前页数据列表)
SortedResultRequestDto 仅排序无分页的查询输入 Sorting(排序规则)

示例:分页查询DTO与结果

// 1. 分页查询输入(继承基础分页类,扩展业务字段)
public class GetBookPagedInput : PagedAndSortedResultRequestDto
{
    public decimal? MinPrice { get; set; } // 扩展:价格下限过滤
    public Guid? AuthorId { get; set; }    // 扩展:按作者ID过滤
}

// 2. 分页查询服务方法(返回PagedResultDto)
public async Task<PagedResultDto<BookDto>> GetPagedAsync(GetBookPagedInput input)
{
    var query = _bookRepo.AsQueryable()
                        .WhereIf(input.MinPrice.HasValue, b => b.Price >= input.MinPrice.Value)
                        .WhereIf(input.AuthorId.HasValue, b => b.AuthorId == input.AuthorId.Value);

    // 计算总条数+分页数据
    var total = await query.CountAsync();
    var items = await query.Skip(input.SkipCount)
                          .Take(input.MaxResultCount)
                          .OrderBy(input.Sorting)
                          .ToListAsync();

    // 转为分页结果DTO
    return new PagedResultDto<BookDto>
    {
        TotalCount = total,
        Items = ObjectMapper.Map<List<Book>, List<BookDto>>(items)
    };
}

四、CRUD扩展辅助类(进阶功能)

针对CRUD的特殊场景(批量操作、软删除、审计),ABP提供专用辅助类:

1. 批量操作辅助类

类名/接口 核心作用 示例用法
IBatchRepository<TEntity, TKey> 批量CRUD操作(高效批量新增/更新) await _batchRepo.InsertManyAsync(bookList);(批量新增)
SqlSugarBatchOperate SqlSugar专属批量操作(支持批量更新/删除) _sqlSugarClient.Updateable(bookList).ExecuteCommandAsync();

2. 软删除与审计辅助类

类名/特性 核心作用 示例用法
ISoftDelete 软删除标记接口(删除时仅标记不物理删除) 实体继承ISoftDelete,自动添加IsDeleted字段
[Audited] 审计日志特性(记录CRUD操作日志) 服务类或方法加[Audited],自动记录操作人、时间、参数
EntityAuditingHelper 手动填充审计字段(非自动场景) _auditingHelper.SetCreationAuditProperties(book);(手动设创建审计)

3. 过滤与查询辅助类

类名/方法 核心作用 示例用法
QueryableExtensions IQueryable扩展方法(简化条件查询) query.WhereIf(!string.IsNullOrEmpty(name), b => b.Name.Contains(name))
DataFilter 全局数据过滤(多租户/软删除自动过滤) using (_dataFilter.Disable<ISoftDelete>()) { /* 查询包含已删除数据 */ }

五、CRUD核心类关系与调用流程

  1. 调用链路:前端请求 → 动态API(自动生成) → CRUD服务类(AbstractXXX) → 仓储类(IRepository) → 数据库
  2. 核心类协作
    • DTO类:定义“输入/输出”格式,通过IObjectMapper与实体转换;
    • 服务类:封装CRUD逻辑,调用仓储操作数据,通过ICurrentUser/IUnitOfWork补充业务信息;
    • 仓储类:底层数据访问,适配不同ORM,屏蔽数据库差异;

六、实战高频场景补充

  1. 部分字段更新:用AbstractKeyCrudAppService,重写MapToEntityAsync,仅赋值输入DTO中有值的字段;
  2. 关联查询:用IQueryableRepository.WithDetailsAsync,关联导航属性(如查书籍时带作者信息);
  3. 批量删除:调用IRepository.DeleteAsync(condition),如await _repo.DeleteAsync(b => b.Price < 0);
  4. 事务保证:服务方法加[UnitOfWork]特性,或用IUnitOfWorkManager手动开启事务,确保多步CRUD原子性。

要不要我帮你整理一份ABP CRUD核心类速查表?包含类名、作用、关键方法和使用场景,方便你开发时快速查询。

三、ABP 框架 CRUD 核心类速查表

1、仓储层核心类(数据访问)

类 / 接口名称 核心作用 关键方法 / 属性 适用场景
IRepository<TEntity, TKey> 通用 CRUD 操作接口(全量功能) InsertAsync/GetAsync/UpdateAsync/DeleteAsync/GetListAsync 基础 CRUD 场景,需增删改查全功能
IReadOnlyRepository<TEntity, TKey> 只读仓储接口(无写入操作) GetAsync/GetListAsync/CountAsync/AnyAsync 纯查询场景(如报表、数据展示)
IQueryableRepository<TEntity, TKey> 支持 IQueryable 的仓储(复杂查询) WithDetailsAsync(关联查询)/AsQueryable 多条件过滤、关联查询、排序分页
EfCoreRepository<TEntity, TKey> EF Core 默认仓储实现 继承IRepository所有方法,支持Include 使用 EF Core 作为 ORM 的项目
SqlSugarRepository<TEntity, TKey> SqlSugar 仓储实现 链式查询(Queryable)/ 批量操作 使用 SqlSugar 作为 ORM,需高性能查询
EfCoreRepositoryBase<TDbContext, TEntity, TKey> 多数据库上下文仓储基类 绑定指定TDbContext,支持多库操作 项目需连接多个数据库(多上下文场景)

2、服务层核心类(CRUD 逻辑封装)

类名 核心作用 关键方法 / 属性 适用场景
AbstractCrudAppService<TEntity, TDto, TKey> 基础 CRUD 服务(输入输出 DTO 一致) 自动实现Get/GetList/Create/Update/Delete 简单 CRUD,查询 / 创建 / 更新用同一 DTO
AbstractKeyCrudAppService<TEntity, TDto, TKey, TGetListInput, TCreateInput, TUpdateInput> 复杂 CRUD 服务(自定义输入 DTO) 支持查询 / 创建 / 更新用不同 DTO,可重写CreateFilteredQueryAsync 多条件查询、部分字段更新、输入验证差异大
CrudAppServiceBase<TEntity, TDto, TKey> 完全自定义 CRUD 服务基类 仅提供仓储和映射工具,需手动实现所有方法 业务逻辑复杂,需完全定制 CRUD 流程
IUnitOfWorkManager 事务管理工具 Begin()(开启事务)/Complete()(提交) 多步 CRUD 操作需保证原子性(要么全成,要么全败)
IObjectMapper DTO 与实体映射工具 Map<TSource, TDestination>() 实体→DTO、DTO→实体的自动转换

3、DTO 层核心类(数据传输)

类名 核心作用 关键属性 / 方法 适用场景
EntityDto<TKey> 基础返回 DTO(带主键) Id(实体主键) 简单查询返回,仅需主键和业务字段
CreationAuditedEntityDto<TKey> 带创建审计的返回 DTO Id/CreationTime(创建时间)/CreatorId(创建人 ID) 需要记录 “谁创建、何时创建” 的场景
AuditedEntityDto<TKey> 带全审计的返回 DTO(创建 + 修改) 继承CreationAuditedEntityDto,增加LastModificationTime/LastModifierId 需要记录 “创建 + 最后修改” 信息的场景
FullAuditedEntityDto<TKey> 带软删除审计的返回 DTO 继承AuditedEntityDto,增加IsDeleted/DeletionTime 支持软删除,需记录删除时间的场景
PagedAndSortedResultRequestDto 分页排序查询输入 DTO Skip(跳过条数)/Take(获取条数)/Sorting(排序规则) 所有列表查询,需分页和排序
PagedResultDto<TDto> 分页查询结果 DTO TotalCount(总条数)/Items(当前页数据) 分页查询的统一返回格式
SortedResultRequestDto 仅排序无分页的查询输入 Sorting(排序规则,如 “Name asc”) 无需分页但需排序的查询(如下拉列表)

4、CRUD 辅助工具类(扩展功能)

类名 / 特性 / 接口 核心作用 关键方法 / 属性 适用场景
ISoftDelete 软删除标记接口 IsDeleted(是否删除) 需逻辑删除(而非物理删除)的实体
[Audited] 审计日志特性 标记服务 / 方法,自动记录操作日志 需要跟踪 CRUD 操作人、时间、参数的场景
QueryableExtensions IQueryable 扩展方法(简化条件查询) WhereIf(condition, expression)(条件成立时才过滤) 动态多条件查询(条件可选)
DataFilter 全局数据过滤工具 Disable<ISoftDelete>()(临时禁用软删除过滤) 需查询已删除数据或多租户数据的特殊场景
IBatchRepository<TEntity, TKey> 批量操作仓储接口 InsertManyAsync/UpdateManyAsync 批量新增、更新多条数据(性能优化)
ICurrentUser 当前用户信息访问器 Id(用户 ID)/IsAuthenticated(是否登录) CRUD 时记录操作人(如CreatorId = CurrentUser.Id

使用建议

  1. 快速开发:简单 CRUD 用 AbstractCrudAppService + IRepository,配合PagedAndSortedResultRequestDto实现分页;
  2. 复杂场景:多条件查询 / 部分更新用 AbstractKeyCrudAppService,自定义输入 DTO;
  3. 查询优化:关联查询用 IQueryableRepository.WithDetailsAsync,批量操作优先用 IBatchRepository
  4. 数据安全:敏感操作加 [UnitOfWork] 保证事务,重要实体继承 FullAuditedEntity 记录全量审计。
posted @ 2025-10-24 21:05  【唐】三三  阅读(6)  评论(0)    收藏  举报