Batch Operations
Files Referenced in this Document
- MyEntityNameAppService.cs
- IMyEntityNameAppService.cs
- IMyEntityNameRepository.cs
- MyEntityName.cs
- EfCoreMyEntityNameRepository.cs
Table of Contents
- Introduction
- Core Component Analysis
- Batch Delete Feature Implementation
- Clone Feature Implementation
- Transaction Consistency and Operation Logs
- Performance Optimization Strategies
- Call Examples and Exception Handling
- Challenges and Solutions in High Concurrency Environments
- Conclusion
Introduction
This document details the technical details of implementing batch delete and clone features in MyEntityNameAppService. It focuses on analyzing the internal logic of the DeleteBatchAsync (referred to as DeleteManyAsync in code) and CloneAsync methods, including how to batch fetch entities via the repository interface IMyEntityNameRepository, handle transaction consistency, and log operations. It also discusses the copying mechanism of core properties during cloning, the generation of new unique identifiers, and the correct reset of audit fields (such as creator, creation time). Furthermore, it discusses performance optimization strategies for batch operations, such as batch processing, asynchronous execution, and database batch support, and provides call examples and exception handling suggestions.
Core Component Analysis
This section analyzes the core classes and interfaces implementing batch operations.
Diagram sources
Section sources
Batch Delete Feature Implementation
The DeleteManyAsync method implements batch deletion of multiple entities. This method receives an ID collection of type IEnumerable<Guid>, iterates through each ID, and calls the DeleteAsync method to delete.
Although named "Batch", it actually deletes entities one by one through a loop, rather than using a database-level batch delete operation. This means each deletion triggers a database transaction, which may affect performance. However, this approach allows for better error control—if a deletion fails, exceptions can be caught to decide whether to continue with subsequent deletions.
Diagram sources
Section sources
Clone Feature Implementation
The CloneAsync method implements entity cloning. Its core logic is as follows:
- Get the current maximum sort value
sortto assign continuous sort numbers to newly cloned entities. - Traverse the passed ID list and get the original entity via
FindAsync. - For each entity, generate a new name: original name + clone tag (defined by
MyEntityNameConsts.CloneTag), and check if the new name already exists; if so, append more tags to ensure uniqueness. - Call the entity's
Clonemethod to create a new instance, passing in the new GUID, new name, and incremented sort number. - Insert the new entity into the database via
InsertAsync.
During cloning, the Clone method of the MyEntityName class only copies core business properties (Code, Name, Remark, Sort), while audit fields (such as CreatorId, CreationTime) are automatically reset to the current user and current time by the base class FullAuditedAggregateRoot<Guid> upon insertion, ensuring the correctness of audit information.
Diagram sources
Section sources
Transaction Consistency and Operation Logs
Although DeleteManyAsync and CloneAsync methods themselves do not explicitly use transaction wrappers, since they run within the context of the ABP framework, by default, each repository operation (such as InsertAsync, DeleteAsync) executes in an independent transaction, ensuring atomicity of single operations.
For CloneAsync, although each insertion is an independent transaction, the method internally ensures logical continuity through sequential execution. If full atomicity of all clone operations (i.e., all succeed or all fail) is required, consider explicitly opening a transaction spanning multiple operations using IUnitOfWorkManager in the application service layer.
Regarding operation logs, the ABP framework's audit function (via inheritance of FullAuditedAggregateRoot<Guid>) automatically records the creator, creation time, last modifier, and last modification time of each entity. These information are correctly reset during cloning, reflecting the framework's good support for audit fields.
Section sources
Performance Optimization Strategies
The current implementation has the following room for performance optimization:
- Batch Database Operations:
DeleteManyAsyncuses loop deletion, which can be optimized to use raw SQL or EF Core'sExecuteDeleteAsyncmethod for true batch deletion, reducing database round trips. - Parallel Processing: For operations without sequential dependencies (such as cloning independent entities), consider using
Parallel.ForEachAsyncorTask.WhenAllfor parallel execution to increase throughput. - Batch Processing: When processing a large number of entities, implement pagination or batching mechanisms to avoid memory overflow caused by loading too much data at once.
- Cache Utilization: Introduce a cache layer to reduce database pressure when frequently querying maximum sort numbers or checking if names exist.
The current EfCoreMyEntityNameRepository implements basic query optimization, such as using Specification pattern and dynamic sorting, but does not provide dedicated interfaces for batch operations.
Section sources
Call Examples and Exception Handling
Call Examples
// Batch Delete
var idsToDelete = new List<Guid> { id1, id2, id3 };
await myEntityNameAppService.DeleteManyAsync(idsToDelete);
// Batch Clone
var idsToClone = new List<Guid> { id1, id2 };
var clonedEntities = await myEntityNameAppService.CloneAsync(idsToClone);
Exception Handling
- Name Conflict:
CloneAsyncinternally checks name uniqueness through a loop to avoidNameAlreadyExistsexception. - Input Validation:
CheckCreateOrUpdateDtoAsyncmethod ensures validity of input data, preventing null values or overly long strings. - Concurrency Conflict: Supports optimistic locking via
SetConcurrencyStampIfNotNullduring entity updates, preventing concurrent modification overwrites.
It is recommended to capture UserFriendlyException at the caller end and display friendly prompts to the user.
Section sources
Challenges and Solutions in High Concurrency Environments
Challenges
- Sort Conflict: Multiple users adjusting sorting simultaneously may cause
AdjustSortAsynccalculation errors. - Name Competition: During high-concurrency cloning, name uniqueness checks may have time windows, leading to duplicate names.
- Performance Bottleneck: Loop deletion/insertion responds slowly under high load.
Solutions
- Distributed Lock: Add locks to sensitive operations like sort adjustment to ensure serial execution.
- Database Constraints: Add unique indexes at the database level as the last line of defense against duplicate names.
- Async Queue: Put batch operations into background task queues (such as Hangfire) to avoid blocking the main thread.
- Optimistic Locking Enhancement: Add version checking in
AdjustSortAsyncto improve concurrency safety.
Section sources
Conclusion
The batch delete and clone features in MyEntityNameAppService implement basic business requirements, utilizing the ABP framework's repository pattern and audit functions to ensure data consistency and traceability. The cloning logic is reasonable, correctly handling unique identifiers and audit field resets. However, the current batch deletion is executed item by item, presenting a performance bottleneck. It is recommended to introduce batch database operations, parallel processing, and distributed lock mechanisms in high concurrency scenarios to improve performance and data security. Future considerations could include optimizing DeleteManyAsync into a true batch operation and providing transactional guarantees for CloneAsync.