feat: criação da transação
This commit is contained in:
@@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user