ABP - CRUD 增删改查 [IRepository、AbstractCrudAppService、AbstractKeyCrudAppService、PagedAndSortedResultRequestDto]
一、CRUD 增删改查
核心辅助类:
- 基于
IRepository的方法:InsertAsync、UpdateAsync、DeleteAsync、GetAsync等。 AbstractCrudAppService<TEntity, TDto, TKey>:基于主键的 CRUD 抽象服务,自动实现Get、GetList、Create、Update、Delete等基础方法。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))。
- 依赖ORM:
IRepository的实现由底层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)。
- 自定义扩展:通过重写父类方法(如
MapToEntityAsync、MapToDtoAsync)添加业务逻辑,不破坏自动实现的基础功能。 - 权限集成:通过
GetPolicyName/CreatePolicyName等属性绑定权限,实现接口授权(需配合ABP权限系统)。
3. AbstractKeyCrudAppService:灵活CRUD服务(复杂版)
AbstractKeyCrudAppService是AbstractCrudAppService的泛型扩展,支持自定义输入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 asc、Price 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> |
只读仓储接口(无写入操作) | GetAsync、GetListAsync、CountAsync(统计)、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 | Id、CreationTime(创建时间)、CreatorId(创建人ID) |
AuditedEntityDto<TKey> |
带全审计的返回DTO(创建+修改) | 继承CreationAuditedEntityDto,增加LastModificationTime、LastModifierId |
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核心类关系与调用流程
- 调用链路:前端请求 → 动态API(自动生成) → CRUD服务类(AbstractXXX) → 仓储类(IRepository) → 数据库
- 核心类协作:
- DTO类:定义“输入/输出”格式,通过
IObjectMapper与实体转换; - 服务类:封装CRUD逻辑,调用仓储操作数据,通过
ICurrentUser/IUnitOfWork补充业务信息; - 仓储类:底层数据访问,适配不同ORM,屏蔽数据库差异;
- DTO类:定义“输入/输出”格式,通过
六、实战高频场景补充
- 部分字段更新:用
AbstractKeyCrudAppService,重写MapToEntityAsync,仅赋值输入DTO中有值的字段; - 关联查询:用
IQueryableRepository.WithDetailsAsync,关联导航属性(如查书籍时带作者信息); - 批量删除:调用
IRepository.DeleteAsync(condition),如await _repo.DeleteAsync(b => b.Price < 0);; - 事务保证:服务方法加
[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) |
使用建议
- 快速开发:简单 CRUD 用
AbstractCrudAppService+IRepository,配合PagedAndSortedResultRequestDto实现分页; - 复杂场景:多条件查询 / 部分更新用
AbstractKeyCrudAppService,自定义输入 DTO; - 查询优化:关联查询用
IQueryableRepository.WithDetailsAsync,批量操作优先用IBatchRepository; - 数据安全:敏感操作加
[UnitOfWork]保证事务,重要实体继承FullAuditedEntity记录全量审计。

浙公网安备 33010602011771号