From d9dfafe07aab3e33a22cfab89ced3e96a9f94942 Mon Sep 17 00:00:00 2001 From: lumijiez <59575049+lumijiez@users.noreply.github.com> Date: Sat, 21 Jun 2025 21:15:10 +0300 Subject: [PATCH] Cool UnitOfWork convenience method (: --- .../Commands/Products/CreateProductHandler.cs | 22 ++++--------- .../Commands/Products/DeleteProductHandler.cs | 30 +++++++---------- src/Imprink.Application/IUnitOfWork.cs | 2 ++ src/Imprink.Infrastructure/UnitOfWork.cs | 33 +++++++++++++++++++ 4 files changed, 52 insertions(+), 35 deletions(-) diff --git a/src/Imprink.Application/Commands/Products/CreateProductHandler.cs b/src/Imprink.Application/Commands/Products/CreateProductHandler.cs index af436bb..ac12e05 100644 --- a/src/Imprink.Application/Commands/Products/CreateProductHandler.cs +++ b/src/Imprink.Application/Commands/Products/CreateProductHandler.cs @@ -16,32 +16,22 @@ public class CreateProductCommand : IRequest public Guid? CategoryId { get; set; } } -public class CreateProductHandler(IUnitOfWork unitOfWork, IMapper mapper) : IRequestHandler +public class CreateProductHandler(IUnitOfWork uw, IMapper mapper) : IRequestHandler { public async Task Handle(CreateProductCommand request, CancellationToken cancellationToken) { - await unitOfWork.BeginTransactionAsync(cancellationToken); - - try + return await uw.TransactAsync(async () => { var product = mapper.Map(request); + var createdProduct = await uw.ProductRepository.AddAsync(product, cancellationToken); - var createdProduct = await unitOfWork.ProductRepository.AddAsync(product, cancellationToken); - if (createdProduct.CategoryId.HasValue) { - createdProduct.Category = (await unitOfWork.CategoryRepository.GetByIdAsync(createdProduct.CategoryId.Value, cancellationToken))!; + createdProduct.Category = + (await uw.CategoryRepository.GetByIdAsync(createdProduct.CategoryId.Value, cancellationToken))!; } - - await unitOfWork.SaveAsync(cancellationToken); - await unitOfWork.CommitTransactionAsync(cancellationToken); return mapper.Map(createdProduct); - } - catch - { - await unitOfWork.RollbackTransactionAsync(cancellationToken); - throw; - } + }, cancellationToken); } } \ No newline at end of file diff --git a/src/Imprink.Application/Commands/Products/DeleteProductHandler.cs b/src/Imprink.Application/Commands/Products/DeleteProductHandler.cs index c4b65ce..2e6c326 100644 --- a/src/Imprink.Application/Commands/Products/DeleteProductHandler.cs +++ b/src/Imprink.Application/Commands/Products/DeleteProductHandler.cs @@ -1,35 +1,27 @@ +using Imprink.Application.Exceptions; using MediatR; namespace Imprink.Application.Commands.Products; -public class DeleteProductCommand : IRequest +public class DeleteProductCommand : IRequest { public Guid Id { get; set; } } -public class DeleteProductHandler(IUnitOfWork unitOfWork) : IRequestHandler +public class DeleteProductHandler(IUnitOfWork uw) : IRequestHandler { - public async Task Handle(DeleteProductCommand request, CancellationToken cancellationToken) + public async Task Handle(DeleteProductCommand request, CancellationToken cancellationToken) { - await unitOfWork.BeginTransactionAsync(cancellationToken); - - try + await uw.TransactAsync(async () => { - var exists = await unitOfWork.ProductRepository.ExistsAsync(request.Id, cancellationToken); + var exists = await uw.ProductRepository.ExistsAsync(request.Id, cancellationToken); + if (!exists) { - await unitOfWork.RollbackTransactionAsync(cancellationToken); - return false; + throw new NotFoundException($"Product with id {request.Id} not found"); } - - await unitOfWork.ProductRepository.DeleteAsync(request.Id, cancellationToken); - await unitOfWork.CommitTransactionAsync(cancellationToken); - return true; - } - catch - { - await unitOfWork.RollbackTransactionAsync(cancellationToken); - throw; - } + + await uw.ProductRepository.DeleteAsync(request.Id, cancellationToken); + }, cancellationToken); } } \ No newline at end of file diff --git a/src/Imprink.Application/IUnitOfWork.cs b/src/Imprink.Application/IUnitOfWork.cs index 4e63857..a3346a2 100644 --- a/src/Imprink.Application/IUnitOfWork.cs +++ b/src/Imprink.Application/IUnitOfWork.cs @@ -17,4 +17,6 @@ public interface IUnitOfWork Task BeginTransactionAsync(CancellationToken cancellationToken = default); Task CommitTransactionAsync(CancellationToken cancellationToken = default); Task RollbackTransactionAsync(CancellationToken cancellationToken = default); + Task TransactAsync(Func> operation, CancellationToken cancellationToken = default); + Task TransactAsync(Func operation, CancellationToken cancellationToken = default); } \ No newline at end of file diff --git a/src/Imprink.Infrastructure/UnitOfWork.cs b/src/Imprink.Infrastructure/UnitOfWork.cs index 1ed1ec9..22011f2 100644 --- a/src/Imprink.Infrastructure/UnitOfWork.cs +++ b/src/Imprink.Infrastructure/UnitOfWork.cs @@ -43,4 +43,37 @@ public class UnitOfWork( { await context.Database.RollbackTransactionAsync(cancellationToken); } + + public async Task TransactAsync(Func> operation, CancellationToken cancellationToken = default) + { + await BeginTransactionAsync(cancellationToken); + try + { + var result = await operation(); + await SaveAsync(cancellationToken); + await CommitTransactionAsync(cancellationToken); + return result; + } + catch + { + await RollbackTransactionAsync(cancellationToken); + throw; + } + } + + public async Task TransactAsync(Func operation, CancellationToken cancellationToken = default) + { + await BeginTransactionAsync(cancellationToken); + try + { + await operation(); + await SaveAsync(cancellationToken); + await CommitTransactionAsync(cancellationToken); + } + catch + { + await RollbackTransactionAsync(cancellationToken); + throw; + } + } } \ No newline at end of file