Cool UnitOfWork convenience method (:

This commit is contained in:
lumijiez
2025-06-21 21:15:10 +03:00
parent ec78744d19
commit d9dfafe07a
4 changed files with 52 additions and 35 deletions

View File

@@ -16,32 +16,22 @@ public class CreateProductCommand : IRequest<ProductDto>
public Guid? CategoryId { get; set; } public Guid? CategoryId { get; set; }
} }
public class CreateProductHandler(IUnitOfWork unitOfWork, IMapper mapper) : IRequestHandler<CreateProductCommand, ProductDto> public class CreateProductHandler(IUnitOfWork uw, IMapper mapper) : IRequestHandler<CreateProductCommand, ProductDto>
{ {
public async Task<ProductDto> Handle(CreateProductCommand request, CancellationToken cancellationToken) public async Task<ProductDto> Handle(CreateProductCommand request, CancellationToken cancellationToken)
{ {
await unitOfWork.BeginTransactionAsync(cancellationToken); return await uw.TransactAsync(async () =>
try
{ {
var product = mapper.Map<Product>(request); var product = mapper.Map<Product>(request);
var createdProduct = await uw.ProductRepository.AddAsync(product, cancellationToken);
var createdProduct = await unitOfWork.ProductRepository.AddAsync(product, cancellationToken);
if (createdProduct.CategoryId.HasValue) 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<ProductDto>(createdProduct); return mapper.Map<ProductDto>(createdProduct);
} }, cancellationToken);
catch
{
await unitOfWork.RollbackTransactionAsync(cancellationToken);
throw;
}
} }
} }

View File

@@ -1,35 +1,27 @@
using Imprink.Application.Exceptions;
using MediatR; using MediatR;
namespace Imprink.Application.Commands.Products; namespace Imprink.Application.Commands.Products;
public class DeleteProductCommand : IRequest<bool> public class DeleteProductCommand : IRequest
{ {
public Guid Id { get; set; } public Guid Id { get; set; }
} }
public class DeleteProductHandler(IUnitOfWork unitOfWork) : IRequestHandler<DeleteProductCommand, bool> public class DeleteProductHandler(IUnitOfWork uw) : IRequestHandler<DeleteProductCommand>
{ {
public async Task<bool> Handle(DeleteProductCommand request, CancellationToken cancellationToken) public async Task Handle(DeleteProductCommand request, CancellationToken cancellationToken)
{ {
await unitOfWork.BeginTransactionAsync(cancellationToken); await uw.TransactAsync(async () =>
try
{ {
var exists = await unitOfWork.ProductRepository.ExistsAsync(request.Id, cancellationToken); var exists = await uw.ProductRepository.ExistsAsync(request.Id, cancellationToken);
if (!exists) if (!exists)
{ {
await unitOfWork.RollbackTransactionAsync(cancellationToken); throw new NotFoundException($"Product with id {request.Id} not found");
return false;
} }
await unitOfWork.ProductRepository.DeleteAsync(request.Id, cancellationToken); await uw.ProductRepository.DeleteAsync(request.Id, cancellationToken);
await unitOfWork.CommitTransactionAsync(cancellationToken); }, cancellationToken);
return true;
}
catch
{
await unitOfWork.RollbackTransactionAsync(cancellationToken);
throw;
}
} }
} }

View File

@@ -17,4 +17,6 @@ public interface IUnitOfWork
Task BeginTransactionAsync(CancellationToken cancellationToken = default); Task BeginTransactionAsync(CancellationToken cancellationToken = default);
Task CommitTransactionAsync(CancellationToken cancellationToken = default); Task CommitTransactionAsync(CancellationToken cancellationToken = default);
Task RollbackTransactionAsync(CancellationToken cancellationToken = default); Task RollbackTransactionAsync(CancellationToken cancellationToken = default);
Task<T> TransactAsync<T>(Func<Task<T>> operation, CancellationToken cancellationToken = default);
Task TransactAsync(Func<Task> operation, CancellationToken cancellationToken = default);
} }

View File

@@ -43,4 +43,37 @@ public class UnitOfWork(
{ {
await context.Database.RollbackTransactionAsync(cancellationToken); await context.Database.RollbackTransactionAsync(cancellationToken);
} }
public async Task<T> TransactAsync<T>(Func<Task<T>> 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<Task> operation, CancellationToken cancellationToken = default)
{
await BeginTransactionAsync(cancellationToken);
try
{
await operation();
await SaveAsync(cancellationToken);
await CommitTransactionAsync(cancellationToken);
}
catch
{
await RollbackTransactionAsync(cancellationToken);
throw;
}
}
} }