using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Storage; using MiningService.Domain.AggregatesModel.MinerAggregate; using MiningService.Domain.AggregatesModel.CircleAggregate; using MiningService.Domain.AggregatesModel.ReferralAggregate; using MiningService.Domain.SeedWork; namespace MiningService.Infrastructure; /// /// EN: Database context for Mining Service. /// VI: Database context cho Mining Service. /// public class MiningServiceContext : DbContext, IUnitOfWork { private IDbContextTransaction? _currentTransaction; public DbSet Miners { get; set; } = null!; public DbSet MiningHistories { get; set; } = null!; public DbSet Circles { get; set; } = null!; public DbSet CircleMembers { get; set; } = null!; public DbSet Referrals { get; set; } = null!; public bool HasActiveTransaction => _currentTransaction != null; public MiningServiceContext(DbContextOptions options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.ApplyConfigurationsFromAssembly(typeof(MiningServiceContext).Assembly); } public async Task SaveEntitiesAsync(CancellationToken cancellationToken = default) { await SaveChangesAsync(cancellationToken); return true; } public async Task BeginTransactionAsync(CancellationToken cancellationToken = default) { if (_currentTransaction != null) return null; _currentTransaction = await Database.BeginTransactionAsync(cancellationToken); return _currentTransaction; } public async Task CommitTransactionAsync(IDbContextTransaction transaction) { if (transaction != _currentTransaction) throw new InvalidOperationException($"Transaction {transaction.TransactionId} is not current"); try { await SaveChangesAsync(); await transaction.CommitAsync(); } catch { RollbackTransaction(); throw; } finally { if (_currentTransaction != null) { await _currentTransaction.DisposeAsync(); _currentTransaction = null; } } } public void RollbackTransaction() { try { _currentTransaction?.Rollback(); } finally { if (_currentTransaction != null) { _currentTransaction.Dispose(); _currentTransaction = null; } } } }