feat: criação da transação

This commit is contained in:
Jean Gatto
2022-06-23 11:49:17 -03:00
parent eab511f48d
commit ed00620c4b
4 changed files with 71 additions and 89 deletions
@@ -0,0 +1,9 @@
using System;
using System.Threading.Tasks;
namespace Shop.Core.Interfaces;
public interface IDataBaseTransaction
{
Task ExecuteAsync(Func<Task> action);
}
@@ -1,54 +1,22 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Shop.Core.Extensions;
using Shop.Infrastructure.Data;
using Shop.Core.Interfaces;
namespace Shop.Infrastructure.Behaviors;
public class TransactionBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse>
public class TransactionBehaviour<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> where TRequest : IRequest<TResponse>
{
private readonly ShopContext _dbContext;
private readonly ILogger<TransactionBehaviour<TRequest, TResponse>> _logger;
private readonly IDataBaseTransaction _dbTransaction;
public TransactionBehaviour(ShopContext dbContext, ILogger<TransactionBehaviour<TRequest, TResponse>> logger)
{
_dbContext = dbContext;
_logger = logger;
}
public TransactionBehaviour(IDataBaseTransaction dbTransaction) => _dbTransaction = dbTransaction;
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
var typeName = request.GetGenericTypeName();
var response = default(TResponse);
try
{
var response = default(TResponse);
await _dbTransaction.ExecuteAsync(async () => response = await next());
var strategy = _dbContext.Database.CreateExecutionStrategy();
await strategy.ExecuteAsync(async () =>
{
var transaction = await _dbContext.BeginTransactionAsync();
_logger.LogInformation("----- Begin transaction {TransactionId} for {CommandName} ({@Command})", transaction.TransactionId, typeName, request);
response = await next();
await _dbContext.CommitTransactionAsync();
_logger.LogInformation("----- Commit transaction {TransactionId} for {CommandName}", transaction.TransactionId, typeName);
});
return response;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error Handling transaction for {CommandName} ({@Command})", typeName, request);
throw;
}
return response;
}
}
@@ -1,8 +1,5 @@
using System.Data;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
namespace Shop.Infrastructure.Data;
@@ -17,51 +14,4 @@ public class ShopContext : DbContext
{
modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
}
#region Transaction
private IDbContextTransaction _currentTransaction;
public async Task<IDbContextTransaction> BeginTransactionAsync()
=> _currentTransaction ??= await Database.BeginTransactionAsync(IsolationLevel.ReadCommitted);
public async Task CommitTransactionAsync()
{
try
{
await SaveChangesAsync();
await _currentTransaction?.CommitAsync();
}
catch
{
await RollbackTransactionAsync();
throw;
}
finally
{
if (_currentTransaction != null)
{
_currentTransaction.Dispose();
_currentTransaction = null;
}
}
}
private async Task RollbackTransactionAsync()
{
try
{
await _currentTransaction?.RollbackAsync();
}
finally
{
if (_currentTransaction != null)
{
_currentTransaction.Dispose();
_currentTransaction = null;
}
}
}
#endregion
}
@@ -0,0 +1,55 @@
using System;
using System.Data;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Shop.Core.Interfaces;
namespace Shop.Infrastructure.Data;
public class ShopContextTransaction : IDataBaseTransaction
{
private readonly ShopContext _dbContext;
private readonly ILogger<ShopContextTransaction> _logger;
public ShopContextTransaction(ShopContext dbContext, ILogger<ShopContextTransaction> logger)
{
_dbContext = dbContext;
_logger = logger;
}
public async Task ExecuteAsync(Func<Task> action)
{
var strategy = _dbContext.Database.CreateExecutionStrategy();
await strategy.ExecuteAsync(async () =>
{
var transaction = await _dbContext.Database.BeginTransactionAsync(IsolationLevel.ReadCommitted);
_logger.LogInformation("----- Begin transaction {TransactionId}", transaction.TransactionId);
await action();
try
{
var rowsAffected = await _dbContext.SaveChangesAsync();
await transaction.CommitAsync();
_logger.LogInformation("----- Commit transaction {TransactionId}, row(s) affected {RowsAffected}", transaction.TransactionId, rowsAffected);
}
catch (Exception ex)
{
_logger.LogError(ex, "An unexpected exception occurred while committing the transaction {TransactionId}", transaction.TransactionId);
await transaction.RollbackAsync();
throw;
}
finally
{
transaction.Dispose();
}
});
}
}