Maik Hasler
Maik Hasler

Reputation: 1400

How to deal with multiple DbContext's and UnitOfWorks

I'm currently trying to introduce the Unit of Work pattern in my .NET application, in order to create a transactional behavior for MediatR:

public sealed class TransactionalBehavior<TCommand, TResponse>(
    ILogger<TransactionBehavior<TCommand, TResponse>> logger,
    IUnitOfWork unitOfWork)
    : IBehavior<TCommand, TResponse>
    where TCommand : class, ICommand<TResponse>
    where TResponse : class
{
    private readonly ILogger<TransactionBehavior<TCommand, TResponse>> _logger = logger;

    private readonly IUnitOfWork _unitOfWork = unitOfWork;

    public async Task<TResponse> Handle(
        TCommand request,
        RequestHandlerDelegate<TResponse> next,
        CancellationToken cancellationToken)
    {
        using var transaction = await _unitOfWork.BeginTransactionAsync(cancellationToken);

        _logger.LogInformation("Started transaction.");

        try
        {
            var response = await next();

            await transaction.CommitAsync(cancellationToken);

            return response;
        }
        catch (Exception)
        {
            await transaction.RollbackAsync(cancellationToken);

            throw;
        }
    }
}

The problem is that I got one DbContext for each module, which all implement the IUnitOfWork on it's own. Therefore I got multiple IUnitOfWork's in my dependency container.

public interface IUnitOfWork
{
    public Task<IDbContextTransaction> BeginTransactionAsync(CancellationToken cancellationToken = default);

    public Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
}

Here is one of the DbContext's as an example:

internal sealed class AuctionhouseDbContext(
    DbContextOptions<AuctionhouseDbContext> options)
    : DbContext(options),
    IUnitOfWork
{
    public const string Schema = "auctionhouse";

    // DbSet<T>'s here...

    protected override void OnModelCreating(
        ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.HasDefaultSchema(Schema);

        modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
    }

    public async Task<IDbContextTransaction> BeginTransactionAsync(
        CancellationToken cancellationToken = default)
    {
        return await Database.BeginTransactionAsync(cancellationToken);
    }
}

Now the question, how can I change the Unit of Work pattern, so that the MediatR behavior resolves the correct IUnitOfWork? I already thought of a generic IUnitOfWork, but I am not sure if this is the most suitable solution.

Does anybody knows how to solve my problem? Thanks in advance

Upvotes: 0

Views: 65

Answers (0)

Related Questions