跳到主要内容
版本:Next

实体管理

本文档中引用的文件

目录

  1. 引言
  2. CRUD操作实现机制
  3. DTO与实体映射机制
  4. 聚合根生命周期与审计字段管理
  5. 软删除处理机制
  6. 分页查询方法对比
  7. 权限控制与数据验证
  8. API调用示例

引言

本文档深入解析MyEntityName实体的CRUD(创建、读取、更新、删除)操作实现机制。围绕IMyEntityNameAppService接口及其具体实现类MyEntityNameAppService,详细阐述业务逻辑流程、对象映射、生命周期管理、审计字段填充、软删除策略、分页查询差异以及安全验证机制。

CRUD操作实现机制

MyEntityNameAppService实现了IMyEntityNameAppService接口,继承自ABP框架的ICrudAppService,提供标准的增删改查功能,并扩展了批量操作、排序调整和导入导出等高级功能。

  • 创建(CreateAsync):接收MyEntityNameCreateDto,校验名称唯一性,生成新实体并插入数据库。
  • 读取(GetAsync / GetListAsync):根据ID获取单个实体或通过分页条件查询列表。
  • 更新(UpdateAsync):加载现有实体,应用DTO中的变更,执行更新。
  • 删除(DeleteAsync / DeleteManyAsync):支持单个或多个ID删除,底层依赖仓储实现软删除。
  • 排序调整(AdjustSortAsync):重新计算所有记录的排序值,确保目标项位于指定位置。
  • 克隆(CloneAsync):复制指定ID的实体,自动处理名称冲突并递增排序。
  • 导入导出(ImportAsync / ExportAsync):支持Excel格式的数据批量导入与导出,包含行级错误反馈。

本节来源

DTO与实体映射机制

系统使用AutoMapper进行DTO与领域实体之间的转换。MyEntityNameAutoMapperProfile定义了从MyEntityNameMyEntityNameDto的映射规则。

关键配置如下:

CreateMap<MyEntityName, MyEntityNameDto>(MemberList.None).MapExtraProperties(MappingPropertyDefinitionChecks.None);
  • MemberList.None表示不验证目标成员,仅映射源中存在的属性。
  • MapExtraProperties启用ABP的扩展属性映射机制,允许动态字段在DTO与实体间传递。

该配置确保了实体属性能正确映射至DTO,同时保留额外的扩展属性(如JSON格式的自定义字段),满足灵活的数据结构需求。

本节来源

聚合根生命周期与审计字段管理

MyEntityName类继承自FullAuditedAggregateRoot<Guid>,这是ABP框架提供的完整审计聚合根基类,自动管理以下审计字段:

审计字段类型说明
CreationTimeDateTime创建时间,由框架自动填充
CreatorIdGuid?创建者用户ID,自动记录
LastModificationTimeDateTime?最后修改时间
LastModifierIdGuid?最后修改者用户ID
IsDeletedbool软删除标志
DeleterIdGuid?删除者用户ID
DeletionTimeDateTime?删除时间

这些字段在实体创建、更新和删除时由ABP框架自动维护,无需手动编码。例如,在调用InsertAsync时,CreationTimeCreatorId会自动设置为当前时间和当前用户。

此外,MyEntityName的构造函数中使用Check.NotNullOrWhiteSpace等方法进行参数校验,确保实体在创建时即满足业务约束。

本节来源

软删除处理机制

系统采用软删除模式,MyEntityName继承的FullAuditedAggregateRoot<Guid>已实现ISoftDelete接口。这意味着调用DeleteAsync不会从数据库中物理删除记录,而是将IsDeleted字段设为true,并记录删除相关信息。

此机制的优势包括:

  • 数据可恢复,避免误删
  • 保留历史关联数据完整性
  • 支持审计追踪

在查询时,默认情况下ABP仓储会自动过滤掉已删除的记录(即IsDeleted == true)。若需包含已删除数据,可在查询时显式指定includeDetails: true参数。

本节来源

分页查询方法对比

MyEntityNameAppService提供了两个分页查询方法:

GetAsync vs GetListAsync

方法用途返回类型是否分页典型场景
GetAsync(Guid id)获取单个实体MyEntityNameDto编辑页面加载详情
GetListAsync(GetMyEntityNamesInput input)查询实体列表PagedResultDto<MyEntityNameDto>列表页面展示

GetListAsync 内部流程

图表来源

GetListAsync使用MyEntityNameSpecification进行条件过滤,并结合filterspecification参数实现复杂查询逻辑,支持按名称模糊匹配等场景。

本节来源

权限控制与数据验证

权限控制

虽然当前代码未直接展示[Authorize]属性,但根据ABP架构惯例,应用服务方法通常通过声明式权限进行保护。权限定义应在CMSPluginMyPluginNameFeatures.cs或相关权限提供程序中配置,确保只有授权用户才能执行CRUD操作。

数据验证

系统采用多层验证机制:

  1. DTO级验证:通过Check.NotNullCheck.NotNullOrWhiteSpace等静态方法在服务层进行前置校验。
  2. 实体级验证:在MyEntityName构造函数和Update方法中再次校验关键字段长度和非空。
  3. 自定义业务规则:如NameExistAsync检查名称唯一性,防止重复提交。

例如,在创建时会调用CheckCreateOrUpdateDtoAsync方法统一验证:

Check.NotNullOrWhiteSpace(input.Code, "编号", MyEntityNameConsts.MaxCodeLength);
Check.NotNullOrWhiteSpace(input.Name, "名称", MyEntityNameConsts.MaxNameLength);

所有验证失败均抛出UserFriendlyException,前端可捕获并友好提示用户。

本节来源

API调用示例

以下为典型API调用场景示例(基于RESTful风格):

创建实体

POST /api/app/my-entity-name
Content-Type: application/json

{
"code": "ENT001",
"name": "示例实体",
"remark": "这是一个测试实体"
}

查询分页列表

GET /api/app/my-entity-name?Filter=示例&Sorting=Name&MaxResultCount=10&SkipCount=0

更新实体

PUT /api/app/my-entity-name/7d8e5d1a-1b2c-4f3d-8e4f-5a6b7c8d9e0a
Content-Type: application/json

{
"code": "ENT001-UPD",
"name": "更新后的实体",
"remark": "已更新"
}

删除实体

DELETE /api/app/my-entity-name/7d8e5d1a-1b2c-4f3d-8e4f-5a6b7c8d9e0a

注意:实际路由前缀可能受模块配置影响,需参考MyEntityNameController定义。

本节来源