namespace HrynCo.DAL.EF.Core; using HrynCo.DAL.Abstract; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Storage; public class EfUnitOfWork : IUnitOfWork where TDbContext : DbContext { private readonly TDbContext _context; private EfTransactionAdapter? _currentTransaction; protected EfUnitOfWork(TDbContext context) { _context = context; } public async Task BeginTransactionAsync(CancellationToken cancellationToken = default) { if (_currentTransaction != null) { return _currentTransaction; } IDbContextTransaction transaction = await _context.Database.BeginTransactionAsync(cancellationToken); _currentTransaction = new EfTransactionAdapter(transaction); return _currentTransaction; } public Task ExecuteInTransactionAsync(Func action) { return ExecuteInTransactionAsync(async () => { await action(); return true; }); } public async Task ExecuteInTransactionAsync(Func> action) { ITransaction? existing = GetCurrentTransaction(); if (existing is not null) { return await action(); } ITransaction tx = await BeginTransactionAsync(); try { TResult result = await action(); await tx.CommitAsync(); return result; } catch { await TryRollbackAsync(tx); throw; } finally { try { await tx.DisposeAsync(); } finally { _currentTransaction = null; } } } private static async Task TryRollbackAsync(ITransaction transaction) { try { await transaction.RollbackAsync(); } catch { // Rollback can fail when the provider has already completed the transaction. // Preserve the action or commit exception that caused the rollback attempt. } } public ITransaction? GetCurrentTransaction() { return _currentTransaction; } }