Files
pos-system/services/fnb-engine-net/src/FnbEngine.Infrastructure/FnbContext.cs

79 lines
3.4 KiB
C#

using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using FnbEngine.Domain.AggregatesModel.TableAggregate;
using FnbEngine.Domain.AggregatesModel.SessionAggregate;
using FnbEngine.Domain.AggregatesModel.KitchenAggregate;
using FnbEngine.Domain.AggregatesModel.RecipeAggregate;
using FnbEngine.Domain.SeedWork;
using FnbEngine.Infrastructure.EntityConfigurations;
namespace FnbEngine.Infrastructure;
public class FnbContext : DbContext, IUnitOfWork
{
private readonly IMediator _mediator;
private IDbContextTransaction? _currentTransaction;
public DbSet<Table> Tables => Set<Table>();
public DbSet<Session> Sessions => Set<Session>();
public DbSet<KitchenTicket> KitchenTickets => Set<KitchenTicket>();
public DbSet<Recipe> Recipes => Set<Recipe>();
public DbSet<RecipeIngredient> RecipeIngredients => Set<RecipeIngredient>();
public IDbContextTransaction? CurrentTransaction => _currentTransaction;
public bool HasActiveTransaction => _currentTransaction != null;
public FnbContext(DbContextOptions<FnbContext> options, IMediator mediator) : base(options)
{
_mediator = mediator ?? throw new ArgumentNullException(nameof(mediator));
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new TableEntityTypeConfiguration());
modelBuilder.ApplyConfiguration(new TableStatusEntityTypeConfiguration());
modelBuilder.ApplyConfiguration(new SessionEntityTypeConfiguration());
modelBuilder.ApplyConfiguration(new KitchenTicketEntityTypeConfiguration());
modelBuilder.ApplyConfiguration(new RecipeEntityTypeConfiguration());
modelBuilder.ApplyConfiguration(new RecipeIngredientEntityTypeConfiguration());
}
public async Task<bool> SaveEntitiesAsync(CancellationToken cancellationToken = default)
{
await DispatchDomainEventsAsync();
await base.SaveChangesAsync(cancellationToken);
return true;
}
public async Task<IDbContextTransaction?> BeginTransactionAsync()
{
if (_currentTransaction != null) return null;
_currentTransaction = await Database.BeginTransactionAsync(System.Data.IsolationLevel.ReadCommitted);
return _currentTransaction;
}
public async Task CommitTransactionAsync(IDbContextTransaction transaction)
{
ArgumentNullException.ThrowIfNull(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) { _currentTransaction.Dispose(); _currentTransaction = null; } }
}
public void RollbackTransaction()
{
try { _currentTransaction?.Rollback(); }
finally { if (_currentTransaction != null) { _currentTransaction.Dispose(); _currentTransaction = null; } }
}
private async Task DispatchDomainEventsAsync()
{
var domainEntities = ChangeTracker.Entries<Entity>().Where(x => x.Entity.DomainEvents.Any()).ToList();
var domainEvents = domainEntities.SelectMany(x => x.Entity.DomainEvents).ToList();
domainEntities.ForEach(entity => entity.Entity.ClearDomainEvents());
foreach (var domainEvent in domainEvents) await _mediator.Publish(domainEvent);
}
}