2
\$\begingroup\$

Previous question: BaseRepository for EF6

I've update my code. Is it correct now? I've changed IEnumerable to IQueryable.

public interface IRepository<T> : IDisposable
{
    T Get(Expression<Func<T, bool>> predicate);
    IQueryable<T> GetWhere(Expression<Func<T, bool>> predicate = null);
    void Add(T entity);
    void Delete(T entity);
    void DeleteWhere(Expression<Func<T, bool>> predicate);
    void Update(T entity);
    void Save();
}

public class BaseRepository<T> : IRepository<T> where T : class
{
    private readonly DbContext _dbContext;

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

    public T Get(Expression<Func<T, bool>> predicate)
    {
        return GetWhere(predicate).FirstOrDefault();
    }

    public IQueryable<T> GetWhere(Expression<Func<T, bool>> predicate = null)
    {
        IQueryable<T> result = _dbContext.Set<T>();
        return (predicate == null) ? result : Queryable.Where<T>(result, predicate);
    }

    public void Add(T entity)
    {
        _dbContext.Entry(entity).State = EntityState.Added;
    }

    public void Delete(T entity)
    {
        _dbContext.Entry(entity).State = EntityState.Deleted;
    }

    public void DeleteWhere(Expression<Func<T, bool>> predicate)
    {
        IQueryable<T> entities = GetWhere(predicate);
        foreach (T entity in entities)
            Delete(entity);
    }

    public void Update(T entity)
    {
        _dbContext.Entry(entity).State = EntityState.Modified;
    }

    public void Save()
    {
        _dbContext.SaveChanges();
    }

    public async void SaveAsync()
    {
        await _dbContext.SaveChangesAsync();
    }

    public void Dispose()
    {
        if (_dbContext != null)
            _dbContext.Dispose();
    }
}
\$\endgroup\$

1 Answer 1

3
\$\begingroup\$

DISCLAIMER I don't believe in wrapping EF with a repository. Entity Framework is a unit-of-work and repository implementation.

I've changed IEnumerable to IQueryable.

You've just destroyed the usefulness of your repository, and leaked Linq-to-Entities to your clients: it doesn't matter what predicate you give GetWhere, the client code can now just say GetWhere().Where(x => whatever);, and the client code now controls when (execution is deferred until the result is iterated) and how the query will run on the database server... and that defeats the purpose of a repository.

What you had before was much more robust.

One of the answerers of your other question said In general, use IQueryable over IEnumerable in your repository. - that did not mean to expose IQueryable.

\$\endgroup\$
8
  • \$\begingroup\$ Thanks for your comment. As I understand, I don't need to cderate repository over EF. I can just use it by creating dataContext in Controllers (I usee it for MVC project)? P.S. - sorry for my Engish) \$\endgroup\$
    – Roman
    Commented May 20, 2014 at 18:52
  • 1
    \$\begingroup\$ I like making a small IUnitOfWork abstraction so I can inject a DbContext as a controller's dependency, and keep my code testable (without hitting db), but yeah, no repository for me ;) \$\endgroup\$ Commented May 20, 2014 at 18:54
  • \$\begingroup\$ I like it! Can you can give me link to github? I want to see some code. \$\endgroup\$
    – Roman
    Commented May 20, 2014 at 18:59
  • 1
    \$\begingroup\$ @Roman this answer shows what I mean :) \$\endgroup\$ Commented May 20, 2014 at 19:02
  • 1
    \$\begingroup\$ @Roman you know about Dependency Injection? I only test the business logic, I trust that EF works as it should - so instead of depending directly on a DbContext I depend on an IUnitOfWork that's implemented by a DbContext - unit tests inject a stub IUnitOfWork that isn't a DbContext. That simple ;) \$\endgroup\$ Commented May 20, 2014 at 19:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.