TanvirArjel/EFCore.GenericRepository

Usage with multiple DbContexts

HybridSolutions opened this issue · 3 comments

How would you use the library with 2 DbContexts (independent from one another)?

services.AddGenericRepository<ApplicationDbContext>();
services.AddGenericRepository<TenantAdminDbContext>();

The issue is now how to inject the "right" repository into a class so that it picks up the correct DbContext?

Found this article and also this one addressing this but would like to get a feedback from you to avoid different directions.

Meanwhile, implemented a solution that can even co-exist with the current one if you just duplicate existing class files. If you like it feel free to use it as a base.

In IRepository.cs
public interface IRepository : IQueryRepository
changes to
public interface IRepositoryBase<TContext> : IQueryRepository where TContext : DbContext

In Repository.cs

internal class Repository : QueryRepository, IRepository
    {
        private readonly DbContext _dbContext;

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

changes to

public class RepositoryBase<TContext> : QueryRepositoryBase<TContext>, IRepositoryBase<TContext> where TContext : DbContext
    {
        private readonly TContext _dbContext;

        public RepositoryBase(TContext context) : base(context)
        {
            _dbContext = context;
        }

In QueryRepository.cs

internal class QueryRepository : IQueryRepository
    {
        private readonly DbContext _dbContext;

        public QueryRepository(DbContext dbContext)
        {
            _dbContext = dbContext;
        }

changes to

public class QueryRepositoryBase<TContext> : IQueryRepository where TContext : DbContext
    {
        private readonly TContext _dbContext;

        public QueryRepositoryBase(TContext context)
        {
            _dbContext = context;
        }

That's it! Now to use DI instead of using

services.AddGenericRepository<ApplicationDbContext>();
services.AddGenericRepository<TenantAdminDbContext>();

just use
services.AddScoped(typeof(IRepositoryBase<>), typeof(RepositoryBase<>));

Now it's possible to use the generic repository with multiple databases. The class just needs to specify the Context to use.

public class UserService : IUserService
{
    private readonly ApplicationDbContext _context;
    private readonly IRepositoryBase<ApplicationDbContext> _repository;

    public UserService(
    ApplicationDbContext context,
    IRepositoryBase<ApplicationDbContext> repository)
    {
        _context = context;
        _repository = repository;
    }
    
    public async Task<IList<User>> GetUsersAsync()
    {
        List<User> users = await _repository.GetListAsync<User>();
        return users;
    }
}

@HybridSolutions I am somewhat busy right now. I shall take a deeper look whenever I get the opportunity.

Has been implemented and will be available in v5.9.0