Junaid
Junaid

Reputation: 1028

Using Inheritance vs Dependency injection with generic Repository in ASP.NET Core

Consider the following generic Repository interface and its implementation:

public interface IRepository<T>
{
    IQueryable<T> FindAll(List<string> includes = null);

    void Add(T entity);

    void Update(T entity);

    void Remove(T entity);
}

public class Repository<T> : IRepository<T> where T : class
{
    protected DatabaseContext _dbContext { get; set; }

    protected ILogger<Repository<T>> _logger { get; set; }
    
    public Repository(DatabaseContext dbContext, ILogger<Repository<T>> logger)
    {
        _logger = logger;
        _dbContext = dbContext;
    }

    public IQueryable<T> FindAll(List<string> includes = null)
    {
        try
        {
            IQueryable<T> items = _dbContext.Set<T>().AsNoTracking();

            if (includes != null && includes.Any())
            {
                includes.Where(i => i != null).ToList().ForEach(i => { items = items.Include(i); });
            }

            return items;
        }
        catch (Exception e)
        {
            _logger.LogError(e, "{Repo} FindAll function error", typeof(Repository<T>));
            return null;
        }
    }

    public void Add(T entity)
    {
        try
        {
            _dbContext.Set<T>().Add(entity);
        }
        catch (Exception e)
        {
            _logger.LogError(e, "{Repo} Add function error", typeof(Repository<T>));
        }
    }

    public void Update(T entity)
    {
        try
        {
            _dbContext.Set<T>().Update(entity);
        }
        catch (Exception e)
        {
            _logger.LogError(e, "{Repo} Update function error", typeof(Repository<T>));
        }
    }

    public void Remove(T entity)
    {
        try
        {
            _dbContext.Set<T>().Remove(entity);
        }
        catch (Exception e)
        {
            _logger.LogError(e, "{Repo} Remove function error", typeof(Repository<T>));
        }
    }
}

In order to use this with a database entity like User, I have two choices.

Either inherit UserRepository implementation from generic Repository:

public class UserRepository : Repository
{
    public UserRepository(MyDbContext context) : base(context)
    {
    }
}

or create an instance of generic IRepository interface in the UserRepository implementation and use dependency injection:

public class UserRepository : IUserRepository
{
    private readonly IRepository _repo;

    public UserRepository(IRepository repo)
    {
        _repo = repo;
    }
}

As per my limited experience with the Repository pattern in ASP.NET Core, I can use either of these and achieve the same results in a CRUD app that uses a database.

My question though is, which one should be used in which scenario?

Update:

I can still create and inject IUserRepository by using the inheritance approach.

public partial interface IUserRepository : IRepository
{
}

public class UserRepository : Repository, IUserRepository
{
    public UserRepository(MyDbContext context) : base(context)
    {
    }
}

Upvotes: 1

Views: 1008

Answers (1)

Athanasios Kataras
Athanasios Kataras

Reputation: 26362

I can't help but notice that the IRepository lost its genetic parameter.

The question to ask here is what you can gain by injecting the IRepository inside your repositories. Are there going to be multiple implementations of the IRepository in your applications lifetime?

Your abstraction here is the repository itself and that's what needs to be injected, not the IRepository itself that I can't see any reason to have multiple or alternate implementations.

As it is also mentioned by Dai in the comments, you should not use it at all. The Generic repository has no point with EF and some people think there is no point at all.

Upvotes: 1

Related Questions