first commit
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Fitness_core_BE.Infra.UoW
|
||||
{
|
||||
public interface IUnitOfWork
|
||||
{
|
||||
Task BeginAsync(CancellationToken ct = default);
|
||||
Task CommitAsync(CancellationToken ct = default);
|
||||
Task RollbackAsync(CancellationToken ct = default);
|
||||
Task SaveChangesAsync(CancellationToken ct = default);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user