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)
{
}
}