跳到主要内容
版本:Next

应用服务实现逻辑

本文档引用的文件

目录

  1. 简介
  2. 依赖注入与服务协调
  3. 核心方法执行流程
  4. 批量操作实现策略
  5. 错误处理与验证机制
  6. 事务边界与性能考量
  7. 扩展性与职责边界

简介

MyEntityNameAppService 是 CMS 插件中负责处理 MyEntityName 实体业务逻辑的核心应用服务。该服务遵循领域驱动设计(DDD)原则,通过依赖注入协调领域实体、仓储接口和对象映射器,实现对实体的增删改查及批量操作。本文档深入分析其具体实现机制,帮助开发者理解服务层的职责划分与扩展方式。

Section sources

依赖注入与服务协调

MyEntityNameAppService 类通过构造函数注入 IMyEntityNameRepository 和继承自基类的 ObjectMapper,实现了对领域层服务的解耦访问。

  • IMyEntityNameRepository:定义了对 MyEntityName 实体的数据访问契约,封装了数据库操作细节。
  • IObjectMapper:由基类 CMSPluginAppService 提供,用于在领域实体 MyEntityName 与数据传输对象 DTO 之间进行自动映射。
  • GuidGenerator:用于生成唯一标识符,确保新实体 ID 的全局唯一性。

这种设计模式将业务编排逻辑集中于应用服务层,同时保持对基础设施和领域模型的低耦合。

Diagram sources

核心方法执行流程

CreateAsync 方法流程

CreateAsync 方法用于创建新的 MyEntityName 实体,执行流程如下:

  1. 调用 CheckCreateOrUpdateDtoAsync 对输入 DTO 进行参数验证。
  2. 检查名称是否已存在,若存在则抛出用户友好异常。
  3. 获取当前最大排序值,作为新实体的默认排序。
  4. 创建新的 MyEntityName 实体实例,并映射扩展属性。
  5. 调用仓储的 InsertAsync 方法持久化实体。
  6. 若指定了排序且与默认值不同,则调用 AdjustSortAsync 调整排序。
  7. 返回映射后的 DTO。

Diagram sources

UpdateAsync 方法流程

UpdateAsync 方法用于更新现有实体:

  1. 执行 DTO 参数验证。
  2. 从仓储获取现有实体。
  3. 检查新名称是否与其他实体冲突(排除自身)。
  4. 更新实体的并发戳(ConcurrencyStamp)和扩展属性。
  5. 调用实体的 Update 方法设置业务字段。
  6. 持久化更新后的实体。
  7. 返回 DTO。

Diagram sources

DeleteAsync 与 GetListAsync 方法

  • DeleteAsync:直接委托给仓储的 DeleteAsync 方法,实现逻辑删除或物理删除。
  • GetListAsync:接收分页和过滤参数,构建查询规范(Specification),调用仓储获取数据总数和列表,并通过 ObjectMapper 映射为 DTO 列表返回。

Section sources

批量操作实现策略

CloneAsync 批量克隆

CloneAsync 方法支持批量克隆多个实体:

  1. 遍历输入的 ID 列表,逐个获取原实体。
  2. 为克隆体生成新名称(添加“副本”标签),并确保名称唯一。
  3. 调用实体的 Clone 方法创建副本,并插入数据库。
  4. 收集所有成功克隆的实体并返回其 DTO 列表。

该方法在循环内执行数据库插入,未使用批量操作,可能影响性能。

DeleteManyAsync 批量删除

DeleteManyAsync 通过遍历 ID 列表并逐个调用 DeleteAsync 实现。此实现方式简单但效率较低,建议在仓储层实现真正的批量删除以提升性能。

ImportAsync 与 ExportAsync

  • ImportAsync:支持从 Excel 导入数据。先进行行级校验(如名称重复),然后分批执行创建或更新操作,具备良好的错误反馈机制。
  • ExportAsync:根据查询条件导出数据,返回字典格式的 Sheet 数据和文件名,便于前端生成 Excel 文件。

Diagram sources

错误处理与验证机制

服务层实现了多层次的错误处理与验证:

  • 参数验证:使用 Check.NotNullCheck.NotNullOrWhiteSpace 等方法进行前置校验。
  • 业务规则验证:如名称唯一性检查,通过 NameExistAsync 方法实现。
  • 用户友好异常:使用 UserFriendlyException 向前端传递可读性高的错误信息。
  • 异常包装:在 ImportAsync 中捕获底层异常并包装为带行号信息的用户友好异常。

Section sources

事务边界与性能考量

  • 事务边界:当前实现依赖于仓储层或数据库上下文的默认事务行为。建议在必要时显式使用 ICurrentUnitOfWork 控制事务。
  • 性能优化
    • GetListAsync 使用分页和过滤,避免全表扫描。
    • AdjustSortAsync 一次性加载所有实体进行排序调整,减少数据库交互次数。
    • 批量操作(如 DeleteManyAsync)存在性能瓶颈,建议在仓储层优化为单次数据库调用。

Section sources

扩展性与职责边界

MyEntityNameAppService 清晰地划分了应用层的职责:

  • 职责:协调领域对象、执行应用级业务逻辑、处理 DTO 转换、管理事务边界。
  • 非职责:不包含复杂领域规则(由实体方法处理),不直接访问数据库(通过仓储)。
  • 扩展方式:可通过继承或添加新方法实现定制逻辑,DTO 和仓储接口支持灵活扩展。

Section sources