Skip to main content
Version: Next

Application Service Implementation Logic

Files referenced in this document

Table of Contents​

  1. Introduction
  2. Dependency Injection and Service Coordination
  3. Core Method Execution Flow
  4. Batch Operation Implementation Strategy
  5. Error Handling and Validation Mechanism
  6. Transaction Boundaries and Performance Considerations
  7. Extensibility and Responsibility Boundaries

Introduction​

MyEntityNameAppService is the core application service in the CMS plugin responsible for handling business logic for the MyEntityName entity. Following Domain-Driven Design (DDD) principles, this service coordinates domain entities, repository interfaces, and object mappers via dependency injection to implement entity CRUD and batch operations. This document deeply analyzes its concrete implementation mechanisms to help developers understand service layer responsibility division and extension methods.

Section sources

Dependency Injection and Service Coordination​

The MyEntityNameAppService class decouples access to domain layer services by injecting IMyEntityNameRepository and the base class inherited ObjectMapper via the constructor.

  • IMyEntityNameRepository: Defines the data access contract for MyEntityName entities, encapsulating database operation details.
  • IObjectMapper: Provided by the base class CMSPluginAppService, used for automatic mapping between domain entity MyEntityName and Data Transfer Objects (DTOs).
  • GuidGenerator: Used to generate unique identifiers, ensuring global uniqueness of new entity IDs.

This design pattern concentrates business orchestration logic in the application service layer while maintaining low coupling with infrastructure and domain models.

Diagram sources

Core Method Execution Flow​

CreateAsync Method Flow​

The CreateAsync method is used to create a new MyEntityName entity, with the following execution flow:

  1. Call CheckCreateOrUpdateDtoAsync to validate input DTO parameters.
  2. Check if the name already exists; if so, throw a user-friendly exception.
  3. Get the current maximum sort value to use as the default sort for the new entity.
  4. Create a new MyEntityName entity instance and map extra properties.
  5. Call the repository's InsertAsync method to persist the entity.
  6. If a sort value is specified and different from the default, call AdjustSortAsync to adjust sorting.
  7. Return the mapped DTO.

Diagram sources

UpdateAsync Method Flow​

The UpdateAsync method is used to update an existing entity:

  1. Execute DTO parameter validation.
  2. Retrieve the existing entity from the repository.
  3. Check if the new name conflicts with other entities (excluding itself).
  4. Update the entity's ConcurrencyStamp and extra properties.
  5. Call the entity's Update method to set business fields.
  6. Persist the updated entity.
  7. Return the DTO.

Diagram sources

DeleteAsync and GetListAsync Methods​

  • DeleteAsync: Directly delegates to the repository's DeleteAsync method to implement logical or physical deletion.
  • GetListAsync: Receives pagination and filtering parameters, builds query specifications, calls the repository to get total count and list, and maps them to a DTO list via ObjectMapper to return.

Section sources

Batch Operation Implementation Strategy​

CloneAsync Batch Clone​

The CloneAsync method supports batch cloning of multiple entities:

  1. Iterate through the input ID list, retrieving original entities one by one.
  2. Generate a new name for the clone (append "Copy" tag) and ensure name uniqueness.
  3. Call the entity's Clone method to create a copy and insert into the database.
  4. Collect all successfully cloned entities and return their DTO list.

This method executes database insertions within a loop and does not use bulk operations, which may affect performance.

DeleteManyAsync Batch Delete​

DeleteManyAsync is implemented by iterating through the ID list and calling DeleteAsync individually. This implementation is simple but less efficient; implementing true batch deletion in the repository layer is recommended for better performance.

ImportAsync and ExportAsync​

  • ImportAsync: Supports importing data from Excel. First performs row-level validation (e.g., duplicate names), then executes create or update operations in batches, with good error feedback mechanisms.
  • ExportAsync: Exports data based on query conditions, returning dictionary-formatted Sheet data and filename, facilitating frontend Excel generation.

Diagram sources

Error Handling and Validation Mechanism​

The service layer implements multi-level error handling and validation:

  • Parameter Validation: Uses Check.NotNull, Check.NotNullOrWhiteSpace, etc., for pre-validation.
  • Business Rule Validation: Checks like name uniqueness via NameExistAsync method.
  • User-Friendly Exceptions: Uses UserFriendlyException to pass readable error information to the frontend.
  • Exception Wrapping: Captures underlying exceptions in ImportAsync and wraps them as user-friendly exceptions with row number information.

Section sources

Transaction Boundaries and Performance Considerations​

  • Transaction Boundaries: Current implementation relies on default transaction behavior of the repository layer or database context. Explicit use of ICurrentUnitOfWork to control transactions is recommended when necessary.
  • Performance Optimization:
    • GetListAsync uses pagination and filtering to avoid full table scans.
    • AdjustSortAsync loads all entities at once for sorting adjustment, reducing database interaction counts.
    • Batch operations (like DeleteManyAsync) have performance bottlenecks; optimizing to single database calls in the repository layer is suggested.

Section sources

Extensibility and Responsibility Boundaries​

MyEntityNameAppService clearly delineates application layer responsibilities:

  • Responsibilities: Coordinating domain objects, executing application-level business logic, handling DTO conversions, managing transaction boundaries.
  • Non-Responsibilities: Does not contain complex domain rules (handled by entity methods), does not directly access the database (via repository).
  • Extension Methods: Custom logic can be implemented via inheritance or adding new methods; DTO and repository interfaces support flexible extension.

Section sources