using LctMonolith.Domain.Entities;
using LctMonolith.Infrastructure.Data;
using LctMonolith.Infrastructure.Repositories;
using Microsoft.EntityFrameworkCore.Storage;
namespace LctMonolith.Infrastructure.UnitOfWork;
///
/// Unit of Work implementation encapsulating repositories and DB transaction scope.
///
public class UnitOfWork : IUnitOfWork, IAsyncDisposable
{
private readonly AppDbContext _ctx;
private IDbContextTransaction? _tx;
public UnitOfWork(AppDbContext ctx)
{
_ctx = ctx;
}
private IGenericRepository? _users;
private IGenericRepository? _ranks;
private IGenericRepository? _rankRequiredMissions;
private IGenericRepository? _rankRequiredCompetencies;
private IGenericRepository? _missions;
private IGenericRepository? _userMissions;
private IGenericRepository? _missionCompetencyRewards;
private IGenericRepository? _missionArtifactRewards;
private IGenericRepository? _competencies;
private IGenericRepository? _userCompetencies;
private IGenericRepository? _artifacts;
private IGenericRepository? _userArtifacts;
private IGenericRepository? _storeItems;
private IGenericRepository? _userInventoryItems;
private IGenericRepository? _transactions;
private IGenericRepository? _eventLogs;
private IGenericRepository? _refreshTokens;
private IGenericRepository? _notifications;
public IGenericRepository Users => _users ??= new GenericRepository(_ctx);
public IGenericRepository Ranks => _ranks ??= new GenericRepository(_ctx);
public IGenericRepository RankRequiredMissions => _rankRequiredMissions ??= new GenericRepository(_ctx);
public IGenericRepository RankRequiredCompetencies => _rankRequiredCompetencies ??= new GenericRepository(_ctx);
public IGenericRepository Missions => _missions ??= new GenericRepository(_ctx);
public IGenericRepository UserMissions => _userMissions ??= new GenericRepository(_ctx);
public IGenericRepository MissionCompetencyRewards => _missionCompetencyRewards ??= new GenericRepository(_ctx);
public IGenericRepository MissionArtifactRewards => _missionArtifactRewards ??= new GenericRepository(_ctx);
public IGenericRepository Competencies => _competencies ??= new GenericRepository(_ctx);
public IGenericRepository UserCompetencies => _userCompetencies ??= new GenericRepository(_ctx);
public IGenericRepository Artifacts => _artifacts ??= new GenericRepository(_ctx);
public IGenericRepository UserArtifacts => _userArtifacts ??= new GenericRepository(_ctx);
public IGenericRepository StoreItems => _storeItems ??= new GenericRepository(_ctx);
public IGenericRepository UserInventoryItems => _userInventoryItems ??= new GenericRepository(_ctx);
public IGenericRepository Transactions => _transactions ??= new GenericRepository(_ctx);
public IGenericRepository EventLogs => _eventLogs ??= new GenericRepository(_ctx);
public IGenericRepository RefreshTokens => _refreshTokens ??= new GenericRepository(_ctx);
public IGenericRepository Notifications => _notifications ??= new GenericRepository(_ctx);
public Task SaveChangesAsync(CancellationToken ct = default) => _ctx.SaveChangesAsync(ct);
public async Task BeginTransactionAsync(CancellationToken ct = default)
{
if (_tx != null) throw new InvalidOperationException("Transaction already started");
_tx = await _ctx.Database.BeginTransactionAsync(ct);
}
public async Task CommitAsync(CancellationToken ct = default)
{
if (_tx == null) return;
try
{
await _ctx.SaveChangesAsync(ct);
await _tx.CommitAsync(ct);
}
catch
{
await RollbackAsync(ct);
throw;
}
finally
{
await _tx.DisposeAsync();
_tx = null;
}
}
public async Task RollbackAsync(CancellationToken ct = default)
{
if (_tx == null) return;
await _tx.RollbackAsync(ct);
await _tx.DisposeAsync();
_tx = null;
}
public async ValueTask DisposeAsync()
{
if (_tx != null) await _tx.DisposeAsync();
}
}