using DigitalData.Core.Abstractions.Application; using DigitalData.Core.Abstractions.Infrastructure; using AutoMapper; using DigitalData.Core.DTO; using DigitalData.Core.Abstractions; using Microsoft.Extensions.Logging; namespace DigitalData.Core.Application { /// /// Provides generic CRUD (Create, Read, Update, Delete) operations for a specified type of entity. /// /// The DTO type for create operations. /// The DTO type for read operations. /// The DTO type for update operations. /// The entity type. /// The type of the identifier for the entity. public class CRUDService : ICRUDService where TCRUDRepository : ICRUDRepository where TCreateDto : class where TReadDto : class where TUpdateDto : IUnique where TEntity : class, IUnique { protected readonly TCRUDRepository _repository; protected readonly IMapper _mapper; /// /// Initializes a new instance of the CRUDService class with the specified repository, translation service, and mapper. /// /// The CRUD repository for accessing the database. /// The AutoMapper instance for mapping between DTOs and entity objects. public CRUDService(TCRUDRepository repository, IMapper mapper) { _repository = repository; _mapper = mapper; } /// /// Asynchronously creates an entity based on the provided create DTO. /// /// The DTO to create an entity from. /// A service result indicating success or failure, including the entity DTO. public virtual async Task> CreateAsync(TCreateDto createDto) { var entity = _mapper.Map(createDto); var createdEntity = await _repository.CreateAsync(entity); return createdEntity is null ? Result.Fail() : Result.Success(createdEntity.Id); } /// /// Asynchronously reads an entity by its identifier and maps it to a read DTO. /// /// The identifier of the entity to read. /// A service result indicating success or failure, including the read DTO if successful. public virtual async Task> ReadByIdAsync(TId id) { var entity = await _repository.ReadByIdAsync(id); return entity is null ? Result.Fail() : Result.Success(_mapper.Map(entity)); } /// /// Asynchronously reads all entities and maps them to read DTOs. /// /// A service result including a collection of read DTOs. public virtual async Task>> ReadAllAsync() { var entities = await _repository.ReadAllAsync(); var readDto = _mapper.Map>(entities); return Result.Success(readDto); } /// /// Asynchronously updates an entity based on the provided update DTO. /// /// The DTO to update an entity from. /// A service message indicating success or failure. public virtual async Task UpdateAsync(TUpdateDto updateDto) { var currentEntitiy = await _repository.ReadByIdAsync(updateDto.Id); if (currentEntitiy is null) return Result.Fail().Notice(LogLevel.Warning, Flag.NotFound, $"{updateDto.Id} is not found in update process of {GetType()} entity."); var entity = _mapper.Map(updateDto, currentEntitiy); return await _repository.UpdateAsync(entity) ? Result.Success() : Result.Fail(); } /// /// Asynchronously deletes an entity by its identifier. /// /// The identifier of the entity to delete. /// A service message indicating success or failure. public virtual async Task DeleteAsyncById(TId id) { TEntity? entity = await _repository.ReadByIdAsync(id); if (entity is null) return Result.Fail(); bool isDeleted = await _repository.DeleteAsync(entity); return isDeleted ? Result.Success() : Result.Fail(); } /// /// Asynchronously checks if an entity with the specified identifier exists. /// /// The identifier of the entity to check. /// A Task that represents the asynchronous operation. The task result contains a boolean value indicating whether the entity exists. public virtual async Task HasEntity(TId id) => await _repository.CountAsync(id) > 0; } }