From 993d407a48c0a71b92a710a5642c3901fc278f0c Mon Sep 17 00:00:00 2001 From: Developer 02 Date: Mon, 16 Sep 2024 09:08:27 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20ReadService=20hinzugef=C3=BCgt=20und=20?= =?UTF-8?q?in=20ReadController=20integriert?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Generischen ReadService erstellt, um Lese- (ReadById, ReadAll) und Löschoperationen zu verwalten. - ReadService in den ReadController integriert. --- DigitalData.Core.API/CRUDControllerBase.cs | 5 +- .../CRUDControllerBaseWithErrorHandling.cs | 5 +- DigitalData.Core.API/ReadControllerBase.cs | 11 ++- .../ReadControllerBaseWithErrorHandling.cs | 8 +- .../Application/IReadService.cs | 2 +- DigitalData.Core.Application/CRUDService.cs | 55 +------------ DigitalData.Core.Application/ReadService.cs | 79 +++++++++++++++++++ DigitalData.Core.DTO/AutoMapperExtension.cs | 23 ------ 8 files changed, 97 insertions(+), 91 deletions(-) create mode 100644 DigitalData.Core.Application/ReadService.cs delete mode 100644 DigitalData.Core.DTO/AutoMapperExtension.cs diff --git a/DigitalData.Core.API/CRUDControllerBase.cs b/DigitalData.Core.API/CRUDControllerBase.cs index f3de4a6..96264ba 100644 --- a/DigitalData.Core.API/CRUDControllerBase.cs +++ b/DigitalData.Core.API/CRUDControllerBase.cs @@ -1,3 +1,4 @@ +using DigitalData.Core.Abstractions; using DigitalData.Core.Abstractions.Application; using DigitalData.Core.DTO; using Microsoft.AspNetCore.Mvc; @@ -19,8 +20,8 @@ namespace DigitalData.Core.API where TCRUDService : ICRUDService where TCreateDto : class where TReadDto : class - where TUpdateDto : class - where TEntity : class + where TUpdateDto : class, IUnique + where TEntity : class, IUnique { protected readonly ILogger _logger; protected readonly TCRUDService _service; diff --git a/DigitalData.Core.API/CRUDControllerBaseWithErrorHandling.cs b/DigitalData.Core.API/CRUDControllerBaseWithErrorHandling.cs index 19a499c..168579f 100644 --- a/DigitalData.Core.API/CRUDControllerBaseWithErrorHandling.cs +++ b/DigitalData.Core.API/CRUDControllerBaseWithErrorHandling.cs @@ -1,3 +1,4 @@ +using DigitalData.Core.Abstractions; using DigitalData.Core.Abstractions.Application; using DigitalData.Core.DTO; using Microsoft.AspNetCore.Mvc; @@ -20,8 +21,8 @@ namespace DigitalData.Core.API where TCRUDService : ICRUDService where TCreateDto : class where TReadDto : class - where TUpdateDto : class - where TEntity : class + where TUpdateDto : class, IUnique + where TEntity : class, IUnique { protected readonly ILogger _logger; protected readonly TCRUDService _service; diff --git a/DigitalData.Core.API/ReadControllerBase.cs b/DigitalData.Core.API/ReadControllerBase.cs index 9bcf578..9ce9446 100644 --- a/DigitalData.Core.API/ReadControllerBase.cs +++ b/DigitalData.Core.API/ReadControllerBase.cs @@ -1,4 +1,3 @@ -using DigitalData.Core.Abstractions; using DigitalData.Core.Abstractions.Application; using DigitalData.Core.DTO; using Microsoft.AspNetCore.Mvc; @@ -13,13 +12,13 @@ namespace DigitalData.Core.API /// The type of the entity's identifier. [ApiController] [Route("api/[controller]")] - public class ReadControllerBase : ControllerBase - where TBasicCRUDService : IBasicCRUDService + public class ReadControllerBase : ControllerBase + where TReadService : IReadService where TReadDto : class - where TEntity : class, IUnique + where TEntity : class { protected readonly ILogger _logger; - protected readonly TBasicCRUDService _service; + protected readonly TReadService _service; /// /// Initializes a new instance of the CRUDControllerBase class with specified logger and CRUD service. @@ -28,7 +27,7 @@ namespace DigitalData.Core.API /// The CRUD service handling business logic for the entity. public ReadControllerBase( ILogger logger, - TBasicCRUDService service) + TReadService service) { _logger = logger; _service = service; diff --git a/DigitalData.Core.API/ReadControllerBaseWithErrorHandling.cs b/DigitalData.Core.API/ReadControllerBaseWithErrorHandling.cs index cf88ce1..b2c3502 100644 --- a/DigitalData.Core.API/ReadControllerBaseWithErrorHandling.cs +++ b/DigitalData.Core.API/ReadControllerBaseWithErrorHandling.cs @@ -13,13 +13,13 @@ namespace DigitalData.Core.API /// The type of the entity's identifier. [ApiController] [Route("api/[controller]")] - public class ReadControllerBaseWithErrorHandling : ControllerBase - where TBasicCRUDService : IBasicCRUDService + public class ReadControllerBaseWithErrorHandling : ControllerBase + where TReadService : IReadService where TReadDto : class where TEntity : class { protected readonly ILogger _logger; - protected readonly TBasicCRUDService _service; + protected readonly TReadService _service; /// /// Initializes a new instance of the CRUDControllerBase class with specified logger and CRUD service. @@ -28,7 +28,7 @@ namespace DigitalData.Core.API /// The CRUD service handling business logic for the entity. public ReadControllerBaseWithErrorHandling( ILogger logger, - TBasicCRUDService service) + TReadService service) { _logger = logger; _service = service; diff --git a/DigitalData.Core.Abstractions/Application/IReadService.cs b/DigitalData.Core.Abstractions/Application/IReadService.cs index a5dc409..132054b 100644 --- a/DigitalData.Core.Abstractions/Application/IReadService.cs +++ b/DigitalData.Core.Abstractions/Application/IReadService.cs @@ -3,7 +3,7 @@ namespace DigitalData.Core.Abstractions.Application { public interface IReadService - where TReadDto : class where TEntity : class, IUnique + where TReadDto : class where TEntity : class { /// /// Retrieves an entity by its identifier and returns its readDTO representation wrapped in an IServiceResult, diff --git a/DigitalData.Core.Application/CRUDService.cs b/DigitalData.Core.Application/CRUDService.cs index 4542961..342c7cb 100644 --- a/DigitalData.Core.Application/CRUDService.cs +++ b/DigitalData.Core.Application/CRUDService.cs @@ -15,21 +15,17 @@ namespace DigitalData.Core.Application /// The DTO type for update operations. /// The entity type. /// The type of the identifier for the entity. - public class CRUDService : ICRUDService + public class CRUDService : ReadService, 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) + public CRUDService(TCRUDRepository repository, IMapper mapper) : base(repository: repository, mapper: mapper) { - _repository = repository; - _mapper = mapper; } /// @@ -44,30 +40,6 @@ namespace DigitalData.Core.Application 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. /// @@ -86,28 +58,5 @@ namespace DigitalData.Core.Application ? 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; } } \ No newline at end of file diff --git a/DigitalData.Core.Application/ReadService.cs b/DigitalData.Core.Application/ReadService.cs new file mode 100644 index 0000000..35499cb --- /dev/null +++ b/DigitalData.Core.Application/ReadService.cs @@ -0,0 +1,79 @@ +using DigitalData.Core.Abstractions.Application; +using DigitalData.Core.Abstractions.Infrastructure; +using AutoMapper; +using DigitalData.Core.DTO; +using DigitalData.Core.Abstractions; + +namespace DigitalData.Core.Application +{ + /// + /// Provides generic Read (Read and Delete) operations for a specified type of entity. + /// + /// The DTO type for read operations. + /// The entity type. + /// The type of the identifier for the entity. + public class ReadService : IReadService + where TCRUDRepository : ICRUDRepository where TReadDto : class 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 ReadService(TCRUDRepository repository, IMapper mapper) + { + _repository = repository; + _mapper = mapper; + } + + /// + /// 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 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; + } +} \ No newline at end of file diff --git a/DigitalData.Core.DTO/AutoMapperExtension.cs b/DigitalData.Core.DTO/AutoMapperExtension.cs deleted file mode 100644 index fa33333..0000000 --- a/DigitalData.Core.DTO/AutoMapperExtension.cs +++ /dev/null @@ -1,23 +0,0 @@ -using AutoMapper; - -namespace DigitalData.Core.DTO -{ - public static class AutoMapperExtension - { - [Obsolete("use mapper.Map")] - /// - /// Maps a source object to a destination object, or throws an exception if the mapping result is null. - /// - /// The source object type. - /// The destination object type. - /// The source object to map from. - /// The mapped destination object. - /// Thrown when the mapping result is null. - public static TDestination MapOrThrow(this IMapper mapper, object source) - { - return mapper.Map(source) ?? throw new AutoMapperMappingException( - $"Mapping to {typeof(TDestination).FullName} resulted in a null object. " + - "Hint: Ensure that the AutoMapper profile configuration for this mapping is correct."); - } - } -} \ No newline at end of file