ardalis / Specification

Base class with tests for adding specifications to a DDD model
MIT License
1.84k stars 240 forks source link

Is it possible to use generic repository approach like this? #375

Closed stamahto closed 6 months ago

stamahto commented 8 months ago

Hi, does anyone have created generic repository with ardalis specifications like this?

public class EmployeeService
{
    private readonly IRepository _repository; // If single DbContext
    private readonly IRepository<YourDbContext1> _dbConext1Repository; // If multiple DbContext

    public EmployeeService(IRepository repository, IRepository<YourDbContext1> dbConext1Repository)
    {
        _repository = repository;
        _dbConext1Repository = dbConext1Repository;
    }

    public async Task<Employee> GetEmployeeAsync(int employeeId)
    {
        Employee employee = await _repository.GetByIdAsync<Employee>(1);
        return employee;
    }
}

I struggle with the genericity of RepositoryBase along with the use of ISpecification param in methods. I can't seem to get it to work together. Thank you.

fiseni commented 6 months ago

Hi @stamahto,

Not sure of your internal infrastructure, but let me provide some general feedback.

Here is the standard approach. You have a generic repository, where T is your entity. Also, in Repository implementation you pass your concrete DbContext to the base.

public interface IRepository<T> : IRepositoryBase<T> where T : class
{
}
public class Repository<T> : RepositoryBase<T>, IRepository<T> where T : class
{
    public Repository(AppDbContext dbContext) : base(dbContext)
    {
    }
}

If you want to work with multiple contexts, then define an additional generic parameter as follows. Notice the where TDbContext : DbContext constraint.

public interface IRepository<TDbContext, T> : IRepositoryBase<T> where T : class
{
}
public class Repository<TDbContext, T> : RepositoryBase<T>, IRepository<TDbContext, T> 
    where T : class where TDbContext : DbContext
{
    public Repository(TDbContext dbContext) : base(dbContext)
    {
    }
}