实体管理
本文档中引用的文件
- IMyEntityNameAppService.cs
- MyEntityNameAppService.cs
- MyEntityNameAutoMapperProfile.cs
- MyEntityName.cs
- IMyEntityNameRepository.cs
目录
引言
本文档深入解析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定义了从MyEntityName到MyEntityNameDto的映射规则。
关键配置如下:
CreateMap<MyEntityName, MyEntityNameDto>(MemberList.None).MapExtraProperties(MappingPropertyDefinitionChecks.None);
MemberList.None表示不验证目标成员,仅映射源中存在的属性。MapExtraProperties启用ABP的扩展属性映射机制,允许动态字段在DTO与实体间传递。
该配置确保了实体属性能正确映射至DTO,同时保留 额外的扩展属性(如JSON格式的自定义字段),满足灵活的数据结构需求。
本节来源
聚合根生命周期与审计字段管理
MyEntityName类继承自FullAuditedAggregateRoot<Guid>,这是ABP框架提供的完整审计聚合根基类,自动管理以下审计字段:
| 审计字段 | 类型 | 说明 |
|---|---|---|
| CreationTime | DateTime | 创建时间,由框架自动填充 |
| CreatorId | Guid? | 创建者用户ID,自动记录 |
| LastModificationTime | DateTime? | 最后修改时间 |
| LastModifierId | Guid? | 最后修改者用户ID |
| IsDeleted | bool | 软删除标志 |
| DeleterId | Guid? | 删除者用户ID |
| DeletionTime | DateTime? | 删除时间 |
这些字段在实体创建、更新和删除时由ABP框架自动维护,无需手动编码。例如,在调用InsertAsync时,CreationTime和CreatorId会自动设置为当前时间和当前用户。
此外,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进行条件过滤,并结合filter和specification参数实现复杂查询逻辑,支持按名称模糊匹配等场景。
本节来源
权限控制与数据验证
权限控制
虽然当前代码未直接展示[Authorize]属性,但根据ABP架构惯例,应用服务方法通常通过声明式权限进行保护。权限定义应在CMSPluginMyPluginNameFeatures.cs或相关权限提供程序中配置,确保只有授权用户才能执行CRUD操作。
数据验证
系统采用多层验证机制:
- DTO级验证:通过
Check.NotNull、Check.NotNullOrWhiteSpace等静态方法在服务层进行前置校验。 - 实体级验证:在
MyEntityName构造函数和Update方法中再次校验关键字段长度和非空。 - 自定义业务规则:如
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定义。
本节来源