Skip to content

Commit

Permalink
1
Browse files Browse the repository at this point in the history
  • Loading branch information
akbaramd committed Dec 31, 2024
1 parent 4218cfc commit e7f65b4
Show file tree
Hide file tree
Showing 26 changed files with 881 additions and 183 deletions.
10 changes: 5 additions & 5 deletions New/Payeh.SharedKernel/EntityFrameworkCore/PayehDbContext.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
using MediatR;
using Microsoft.EntityFrameworkCore;
using Payeh.SharedKernel.Domain;
using Payeh.SharedKernel.UnitOfWork;

namespace Payeh.SharedKernel.EntityFrameworkCore;

public class PayehDbContext<TDbContext> : DbContext,IPayehDbContext where TDbContext : DbContext
{
private readonly IMediator _mediator;

public PayehDbContext(DbContextOptions<TDbContext> options, IMediator mediator) : base(options)
private readonly IUnitOfWorkManager _unitOfWorkManager;
public PayehDbContext(DbContextOptions<TDbContext> options , IUnitOfWorkManager unitOfWorkManager) : base(options)
{
_mediator = mediator;
_unitOfWorkManager =unitOfWorkManager;
}

public override int SaveChanges()
Expand Down Expand Up @@ -43,7 +43,7 @@ private async Task PublishDomainEventsAsync()
// Publish domain events
foreach (var domainEvent in domainEvents)
{
await _mediator.Publish(domainEvent);
_unitOfWorkManager.CurrentUnitOfWork.AddDomainEvent(domainEvent);
}

// Clear domain events
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,9 @@ public void ClearDomainEvents()
throw new InvalidOperationException("Failed to clear domain events from the DbContext.", ex);
}
}

public void Dispose()
{
DbContext.Dispose();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ public EfCoreUnitofWOrkTransactionManager(IPayehDbContext dbContext, IDbContextT
/// <summary>
/// Commits the current transaction.
/// </summary>
public void CommitTransaction()
public async Task CommitTransactionAsync()
{
try
{
_transaction?.Commit();
await _transaction?.CommitAsync()!;
}
catch (Exception ex)
{
Expand All @@ -37,11 +37,11 @@ public void CommitTransaction()
/// <summary>
/// Rolls back the current transaction.
/// </summary>
public void RollbackTransaction()
public async Task RollbackTransactionAsync()
{
try
{
_transaction?.Rollback();
await _transaction?.RollbackAsync()!;
}
catch (Exception ex)
{
Expand Down
134 changes: 134 additions & 0 deletions New/Payeh.SharedKernel/UnitOfWork/ChildUnitOfWork.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
using MediatR;
using Payeh.SharedKernel.EntityFrameworkCore;

namespace Payeh.SharedKernel.UnitOfWork.Child
{
/// <summary>
/// A child UnitOfWork that delegates all operations to a parent <see cref="IUnitOfWork"/>.
/// This allows you to create nested UoW layers (logically) without duplicating
/// the transactional state or resources.
/// </summary>
public class ChildUnitOfWork : IUnitOfWork
{
private readonly IUnitOfWork _parentUow;


/// <summary>
/// Creates a new ChildUnitOfWork that delegates everything to <paramref name="parentUow"/>.
/// </summary>
public ChildUnitOfWork(IUnitOfWork parentUow)
{
_parentUow = parentUow ?? throw new ArgumentNullException(nameof(parentUow));
_parentUow.Disposed += (sender, args) =>
{
Disposed?.Invoke(sender!, args);
};
}

/// <summary>
/// In most child implementations, we use the parent's Id
/// since they share the same underlying transaction/logical scope.
/// </summary>
public Guid Id => _parentUow.Id;

/// <summary>
/// Returns the parent's options, effectively inheriting them.
/// </summary>
public IUnitOfWorkOptions Options => _parentUow.Options;

/// <summary>
/// Event that is typically raised on disposal,
/// but we forward it to the parent so consumers can subscribe in a single place.
/// </summary>
public event EventHandler Disposed = default!;

#region Transaction Management

public void AddTransaction(string key, IUnitofWOrkTransactionManager unitofWOrkTransactionManager)
=> _parentUow.AddTransaction(key, unitofWOrkTransactionManager);

public IUnitofWOrkTransactionManager? GetTransaction(string key)
=> _parentUow.GetTransaction(key);

public IEnumerable<string> GetTransactionKeys()
=> _parentUow.GetTransactionKeys();

public void CommitTransaction(string key)
=> _parentUow.CommitTransaction(key);

public Task CommitTransactionAsync(string key, CancellationToken cancellationToken = default)
=> _parentUow.CommitTransactionAsync(key, cancellationToken);

public void RollbackTransaction(string key)
=> _parentUow.RollbackTransaction(key);

public Task RollbackTransactionAsync(string key, CancellationToken cancellationToken = default)
=> _parentUow.RollbackTransactionAsync(key, cancellationToken);

#endregion

#region Data Storage Management

public void AddDataStorage(string key, IUnitOfWOrtDatabaseManager unitOfWOrtDatabaseManager)
=> _parentUow.AddDataStorage(key, unitOfWOrtDatabaseManager);

public IUnitOfWOrtDatabaseManager? GetDataStorage(string key)
=> _parentUow.GetDataStorage(key);

public IEnumerable<string> GetDataStorageKeys()
=> _parentUow.GetDataStorageKeys();

#endregion

#region Global Operations

/// <summary>
/// Typically, a child does not finalize (commit) the entire UoW.
/// However, you can choose to delegate it to the parent if desired.
/// </summary>
public void CommitAll()
=> _parentUow.CommitAll();

public Task CommitAsync(CancellationToken cancellationToken = default)
{
return Task.CompletedTask;
}
public void RollbackAll()
=> _parentUow.RollbackAll();

public Task RollbackAsync(CancellationToken cancellationToken = default)
=> _parentUow.RollbackAsync(cancellationToken);

public void Initialize(IUnitOfWorkOptions options)
=> _parentUow.Initialize(options);

public void AddDomainEvent(INotification domainEvent)
{
_parentUow.AddDomainEvent(domainEvent);
}



#endregion

#region IDisposable

/// <summary>
/// Disposing the child typically does NOT dispose the parent,
/// so here you can either do nothing or just remove event handlers, etc.
/// </summary>
public void Dispose()
{


}

#endregion

/// <summary>
/// For diagnostics/logging.
/// </summary>
public override string ToString()
=> $"[ChildUnitOfWork => ParentId: {_parentUow.Id}]";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ public interface IUnitOfWOrtDatabaseManager
{
Task SaveChangesAsync(CancellationToken cancellationToken = default);
IEnumerable<IDomainEvent> GetDomainEvents();
void ClearDomainEvents
();
void ClearDomainEvents();
void Dispose();
}
35 changes: 29 additions & 6 deletions New/Payeh.SharedKernel/UnitOfWork/IUnitOfWork.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
namespace Payeh.SharedKernel.UnitOfWork
using MediatR;
using Payeh.SharedKernel.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace Payeh.SharedKernel.UnitOfWork
{
/// <summary>
/// Represents the Unit of Work pattern, encapsulating transaction and data storage management.
/// Includes support for domain events.
/// </summary>
public interface IUnitOfWork : IDisposable
{
public Guid Id { get; set; }
public IUnitOfWorkOptions Options { get; }
public event EventHandler? Disposed;
// Core Properties
Guid Id { get; }
IUnitOfWorkOptions Options { get; }
event EventHandler? Disposed;

// Transaction Management
void AddTransaction(string key, IUnitofWOrkTransactionManager unitofWOrkTransactionManager);
IUnitofWOrkTransactionManager? GetTransaction(string key);
Expand All @@ -25,7 +38,17 @@ public interface IUnitOfWork : IDisposable
void RollbackAll();
Task RollbackAsync(CancellationToken cancellationToken = default);
void Initialize(IUnitOfWorkOptions options);

// Domain Events Management
/// <summary>
/// Adds a domain event to be published upon committing the Unit of Work.
/// </summary>
/// <param name="domainEvent">The domain event to add.</param>
void AddDomainEvent(INotification domainEvent);


}

// Supporting Interface for Transaction
}
// Supporting Interfaces for Transaction and Data Storage Managers
// (Assumed to be defined elsewhere)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
public interface IUnitofWOrkTransactionManager
{

void CommitTransaction();
void RollbackTransaction();
Task CommitTransactionAsync();
Task RollbackTransactionAsync();
void Dispose();
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,9 @@ public void ClearDomainEvents()
{
// Do nothing, as there are no domain events to clear
}

public void Dispose()
{

}
}
20 changes: 18 additions & 2 deletions New/Payeh.SharedKernel/UnitOfWork/Null/NullUnitOfWork.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
using Payeh.SharedKernel.EntityFrameworkCore;
using MediatR;
using Payeh.SharedKernel.EntityFrameworkCore;

namespace Payeh.SharedKernel.UnitOfWork.Null
{
public class NullUnitOfWork : IUnitOfWork
{
public Guid Id { get; set; } = Guid.NewGuid();
public Guid Id { get; } = Guid.NewGuid();
public IUnitOfWorkOptions Options { get; } = new UnitOfWorkOptions();
public event EventHandler? Disposed;

Expand Down Expand Up @@ -32,6 +33,21 @@ public void Initialize(IUnitOfWorkOptions options)

}

public void AddDomainEvent(INotification domainEvent)
{

}

public IReadOnlyCollection<INotification> GetDomainEvents()
{
return [];
}

public void ClearDomainEvents()
{

}

// Transaction Management - Do Nothing
public void BeginTransaction() { }
public void Commit() { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ public class NullUnitofWOrkTransactionManager : IUnitofWOrkTransactionManager
private NullUnitofWOrkTransactionManager() { }

public void BeginTransaction() { }
public void CommitTransaction() { }
public void RollbackTransaction() { }

public Task CommitTransactionAsync()
{
return Task.CompletedTask;
}

public Task RollbackTransactionAsync()
{
return Task.CompletedTask;
}
public void Dispose()
{

}
}
Loading

0 comments on commit e7f65b4

Please sign in to comment.