using System.Text.Json; using BuildingBlocks.Core; using MediatR; using Microsoft.Extensions.Logging; namespace BuildingBlocks.EFCore; public class EfTxBehavior : IPipelineBehavior where TRequest : notnull, IRequest where TResponse : notnull { private readonly ILogger> _logger; private readonly IDbContext _dbContextBase; private readonly IEventDispatcher _eventDispatcher; public EfTxBehavior( ILogger> logger, IDbContext dbContextBase, IEventDispatcher eventDispatcher) { _logger = logger; _dbContextBase = dbContextBase; _eventDispatcher = eventDispatcher; } public async Task Handle(TRequest request, RequestHandlerDelegate next, CancellationToken cancellationToken) { _logger.LogInformation( "{Prefix} Handled command {MediatrRequest}", nameof(EfTxBehavior), typeof(TRequest).FullName); _logger.LogDebug( "{Prefix} Handled command {MediatrRequest} with content {RequestContent}", nameof(EfTxBehavior), typeof(TRequest).FullName, JsonSerializer.Serialize(request)); _logger.LogInformation( "{Prefix} Open the transaction for {MediatrRequest}", nameof(EfTxBehavior), typeof(TRequest).FullName); await _dbContextBase.BeginTransactionAsync(cancellationToken); try { var response = await next(); _logger.LogInformation( "{Prefix} Executed the {MediatrRequest} request", nameof(EfTxBehavior), typeof(TRequest).FullName); var domainEvents = _dbContextBase.GetDomainEvents(); await _eventDispatcher.SendAsync(domainEvents.ToArray(), typeof(TRequest), cancellationToken); await _dbContextBase.CommitTransactionAsync(cancellationToken); return response; } catch (System.Exception ex) { await _dbContextBase.RollbackTransactionAsync(cancellationToken); throw; } } }