Recently I start working on open source project using ASP.Net Core 2.0 & ReactJS
you guy can take a look at
Awesome CMS-Core
So every web application need database to working with (obviously). So to follow
DRY
principles we need some generic way to manipulate with our database (keep create same class with same behaviour just different entity).
In this post I will show you guys how to implement simple Generic Repository Pattern that could reuse for every web application.
Full source code can be found
here
First I need to add interface
public interface IGenericRepository<T> where T : class
IQueryable<T> Query();
ICollection<T> GetAll();
Task<ICollection<T>> GetAllAsync();
T GetById(int id);
Task<T> GetByIdAsync(int id);
T GetByUniqueId(string id);
Task<T> GetByUniqueIdAsync(string id);
T Find(Expression<Func<T, bool>> match);
Task<T> FindAsync(Expression<Func<T, bool>> match);
ICollection<T> FindAll(Expression<Func<T, bool>> match);
Task<ICollection<T>> FindAllAsync(Expression<Func<T, bool>> match);
T Add(T entity);
Task<T> AddAsync(T entity);
T Update(T updated);
Task<T> UpdateAsync(T updated);
void Delete(T t);
Task<int> DeleteAsync(T t);
int Count();
Task<int> CountAsync();
IEnumerable<T> Filter(
Expression<Func<T, bool>> filter = null,
Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null,
string includeProperties = "",
int? page = null,
int? pageSize = null);
IQueryable<T> FindBy(Expression<Func<T, bool>> predicate);
bool Exist(Expression<Func<T, bool>> predicate);
Something we need to pay attention is the T keyword on the of interface. That is where our Entity being pass in.
And next is our implementation of GenericRepository
public class GenericRepository<T> : IGenericRepository<T> where T : class
private readonly ApplicationDbContext _context;
private readonly IUnitOfWork _unitOfWork;
public GenericRepository(ApplicationDbContext context)
_context = context;
_unitOfWork = new UnitOfWork(context);
public IQueryable<T> Query()
return _context.Set<T>().AsQueryable();
public ICollection<T> GetAll()
return _context.Set<T>().ToList();
public async Task<ICollection<T>> GetAllAsync()
return await _context.Set<T>().ToListAsync();
public T GetById(int id)
return _context.Set<T>().Find(id);
public async Task<T> GetByIdAsync(int id)
return await _context.Set<T>().FindAsync(id);
public T GetByUniqueId(string id)
return _context.Set<T>().Find(id);
public async Task<T> GetByUniqueIdAsync(string id)
return await _context.Set<T>().FindAsync(id);
public T Find(Expression<Func<T, bool>> match)
return _context.Set<T>().SingleOrDefault(match);
public async Task<T> FindAsync(Expression<Func<T, bool>> match)
return await _context.Set<T>().SingleOrDefaultAsync(match);
public ICollection<T> FindAll(Expression<Func<T, bool>> match)
return _context.Set<T>().Where(match).ToList();
public async Task<ICollection<T>> FindAllAsync(Expression<Func<T, bool>> match)
return await _context.Set<T>().Where(match).ToListAsync();
public T Add(T entity)
_context.Set<T>().Add(entity);
_context.SaveChanges();
return entity;
public async Task<T> AddAsync(T entity)
_context.Set<T>().Add(entity);
await _unitOfWork.Commit();
return entity;
public T Update(T updated)
if (updated == null)
return null;
_context.Set<T>().Attach(updated);
_context.Entry(updated).State = EntityState.Modified;
_context.SaveChanges();
return updated;
public async Task<T> UpdateAsync(T updated)
if (updated == null)
return null;
_context.Set<T>().Attach(updated);
_context.Entry(updated).State = EntityState.Modified;
await _unitOfWork.Commit();
return updated;
public void Delete(T t)
_context.Set<T>().Remove(t);
_context.SaveChanges();
public async Task<int> DeleteAsync(T t)
_context.Set<T>().Remove(t);
return await _unitOfWork.Commit();
public int Count()
return _context.Set<T>().Count();
public async Task<int> CountAsync()
return await _context.Set<T>().CountAsync();
public IEnumerable<T> Filter(Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, string includeProperties = "", int? page = null,
int? pageSize = null)
IQueryable<T> query = _context.Set<T>();
if (filter != null)
query = query.Where(filter);
if (orderBy != null)
query = orderBy(query);
if (includeProperties != null)
foreach (
var includeProperty in includeProperties.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
query = query.Include(includeProperty);
if (page != null && pageSize != null)
query = query.Skip((page.Value - 1) * pageSize.Value).Take(pageSize.Value);
return query.ToList();
public IQueryable<T> FindBy(Expression<Func<T, bool>> predicate)
return _context.Set<T>().Where(predicate);
public bool Exist(Expression<Func<T, bool>> predicate)
var exist = _context.Set<T>().Where(predicate);
return exist.Any() ? true : false;
I give 2 options for you guys to choose. Is async query and non async query. But my suggest is go for async query.
Next is the UnitOfWork you guys can take a look at
here
Last thing, in order to use generic repository in our service class or what ever you want to call. We have to register in our Startup.cs class
services.AddScoped(typeof(IGenericRepository<>), typeof(GenericRepository<>));
services.AddTransient<IUnitOfWork, UnitOfWork>();
To use in our controller class or service class. We only need to use DI pattern like this
private readonly IGenericRepository〈User〉 _userRepository;
public AccountController(
IGenericRepository〈User〉 userRepository
_userRepository = userRepository;
public async Task GetAllUser() {
var data = await _userRepository.GetAllAsync();
// reset of code
That is. In my next post I will introduce UnitOfWork pattern and how to implement it to clean up our GenericRepository code. Happy coding !!!!
Please provide a sample code as unitofwork and Iunitofwork class/interface missing in above example
I’m already add in here
https://ngohungphuc.wordpress.com/2018/05/02/unit-of-work-pattern-in-asp-net-core/
Is the issue with this approach not that the repository is loosely typed? I think for simple implementations of a class this is fine, but if you want a strongly typed class is this not an issue?
Enter your email address to subscribe to this blog and receive notifications of new posts by email.
Email Address:
Privacy & Cookies: This site uses cookies. By continuing to use this website, you agree to their use.
To find out more, including how to control cookies, see here:
Cookie Policy