ardalis / Specification

Base class with tests for adding specifications to a DDD model

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Using UnitOfWork along with the Specifications

messaddek opened this issue · comments

Hello,
Is there any way to use _unitOfWork with the Repository Implemented in your code ?
In my handlers, i have to interact with many tables in same transaction, i've seen in your code that you call SaveChangesAsync in Add / Update.
Many thanks for the code.

The default repo implementation isn't designed to work with unitofwork but you can override it or just copy/paste it and modify it to suit your needs.

Thank you, but, what do you suggest in term of DDD approach ? Handle multiple aggregate root updates in the same db transaction or working with domain events ? If we consider that both updates should be in the same transaction ?
Many thanks

Hi @messaddek,

We have included SaveChangesAsync in those methods since that's what most of the users were asking for. You can overload the methods as follows:

public interface IRepository<T> : IRepositoryBase<T> where T : class
{
}

public class Repository<T> : RepositoryBase<T>, IRepository<T> where T : class
{
  private readonly AppDbContext _dbContext;

  public Repository(AppDbContext dbContext)
    : base(dbContext)
  {
    _dbContext = dbContext;
  }

  public override Task<T> AddAsync(T entity, CancellationToken cancellationToken = default)
  {
    _dbContext.Set<T>().Add(entity);

    return Task.FromResult(entity);
  }
}

On the other hand, if you want the saving to be conditional, then you can add overloads (you can't override since the signature has an extra parameter).

public interface IRepository<T> : IRepositoryBase<T> where T : class
{
  Task<T> AddAsync(T entity, bool saveChanges = true, CancellationToken cancellationToken = default);
}

public class Repository<T> : RepositoryBase<T>, IRepository<T> where T : class
{
  private readonly AppDbContext _dbContext;

  public Repository(AppDbContext dbContext)
    : base(dbContext)
  {
    _dbContext = dbContext;
  }

  public async Task<T> AddAsync(T entity, bool saveChanges = true, CancellationToken cancellationToken = default)
  {
    _dbContext.Set<T>().Add(entity);

    if (saveChanges)
    {
      await SaveChangesAsync(cancellationToken);
    }

    return entity;
  }
}

Then, simply use it as follows. Or, you can have a separate full implementation of UoW.

  await repo.AddAsync(customer, saveChanges: false);

Thank you, I've already checked all your code. and I had the same approach to resolve the problem I've raised. I just asked from a DDD approach, which implementation would be the more accurate with concerns Segregations.

We do not plan to update the signature of the methods since even with optional parameters might be a breaking change for consumers. And the majority of the consumers want the SaveChanges as part of the methods.

Closing the issue.