76 lines
2.9 KiB
C#
76 lines
2.9 KiB
C#
using Microsoft.EntityFrameworkCore.Storage;
|
|
|
|
namespace Fitness_core_BE.Infra.UoW
|
|
{
|
|
public class EFUnitOfWork : IUnitOfWork
|
|
{
|
|
// Central and tenant are separate physical connections -- each gets its own local
|
|
// transaction. There is no distributed-transaction coordinator wired up, so if one
|
|
// side's commit fails after the other has already committed, that is NOT rolled back
|
|
// atomically; true cross-DB atomicity is deferred to a saga/compensating-action
|
|
// pattern (see the migration plan's Phase 2 step 8). Both sides are always
|
|
// begun/committed/rolled-back together so ordinary success/failure flows (the vast
|
|
// majority of call sites) still behave exactly as the single-context version did.
|
|
private readonly CentralDbContext _central;
|
|
private readonly TenantDbContext _tenant;
|
|
private IDbContextTransaction? _centralTransaction;
|
|
private IDbContextTransaction? _tenantTransaction;
|
|
|
|
public EFUnitOfWork(CentralDbContext central, TenantDbContext tenant)
|
|
{
|
|
_central = central;
|
|
_tenant = tenant;
|
|
}
|
|
|
|
public async Task BeginAsync(CancellationToken ct = default)
|
|
{
|
|
if (_centralTransaction == null)
|
|
_centralTransaction = await _central.Database.BeginTransactionAsync(ct);
|
|
if (_tenantTransaction == null)
|
|
_tenantTransaction = await _tenant.Database.BeginTransactionAsync(ct);
|
|
}
|
|
|
|
public async Task SaveChangesAsync(CancellationToken ct = default)
|
|
{
|
|
await _central.SaveChangesAsync(ct);
|
|
await _tenant.SaveChangesAsync(ct);
|
|
}
|
|
|
|
public async Task CommitAsync(CancellationToken ct = default)
|
|
{
|
|
await _central.SaveChangesAsync(ct);
|
|
await _tenant.SaveChangesAsync(ct);
|
|
|
|
if (_centralTransaction != null)
|
|
{
|
|
await _centralTransaction.CommitAsync(ct);
|
|
await _centralTransaction.DisposeAsync();
|
|
_centralTransaction = null;
|
|
}
|
|
if (_tenantTransaction != null)
|
|
{
|
|
await _tenantTransaction.CommitAsync(ct);
|
|
await _tenantTransaction.DisposeAsync();
|
|
_tenantTransaction = null;
|
|
}
|
|
}
|
|
|
|
public async Task RollbackAsync(CancellationToken ct = default)
|
|
{
|
|
if (_centralTransaction != null)
|
|
{
|
|
await _centralTransaction.RollbackAsync(ct);
|
|
await _centralTransaction.DisposeAsync();
|
|
_centralTransaction = null;
|
|
}
|
|
if (_tenantTransaction != null)
|
|
{
|
|
await _tenantTransaction.RollbackAsync(ct);
|
|
await _tenantTransaction.DisposeAsync();
|
|
_tenantTransaction = null;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|