palroj
palroj

Reputation: 151

Generic Repository questions

I'm developing a generic repository for my application and I'm having a few doubts here.

This is some of the code I have for the generic repository:

public interface IEntityRepository<T> where T : class
{
    void Add(T entity);
    T GetById(int id);
    IEnumerable<T> Get(Expression<Func<T, bool>> predicate);
    IEnumerable<T> GetAll();
}

public class EntityRepository<T> : IDisposable, IEntityRepository<T> where T : class
{
    protected DbSet<T> DbSet;
    protected DbContext Context;

    public EntityRepository(DbContext dataContext)
    {
        DbSet = dataContext.Set<T>();
        Context = dataContext;
    }

    public void Add(T entity)
    {
        DbSet.Add(entity);
    }

    public IEnumerable<T> Get(Expression<Func<T, bool>> predicate)
    {
        return DbSet.Where(predicate);
    }

    public IEnumerable<T> GetAll()
    {
        return DbSet;
    }

    public T GetById(int id)
    {
        return DbSet.Find(id);
    }

    // IDisposable
    public void Dispose()
    {
        if (Context != null)
        {
            Context.Dispose();
        }
        GC.SuppressFinalize(this);
    }
}

What I'm having difficulties with is this:

1 - should I be returning IEnumerable from the repository layer to the services layer instead of IQueryable? I've read some articles on the web on this topic but couldn't find a definitive - or reasonably definitive - answer to this question. By returning IEnumerable all subsequent queries will be done locally right?

2 - One thing that will obviously be needed is to be able to retrieve paged data. I don't want to get 100,000 records just to show 50. My question is if this "logic" should be on the repository or in the service, ie, the service gets all the data and then skips/takes however it needs or the repository already returns only the data that the service will need? Or should these types of methods be in the a specific repository that inherits the generic one?

Thanks in advance

Upvotes: 3

Views: 383

Answers (1)

MikeSW
MikeSW

Reputation: 16348

Never return IQueryable since it's an implementation detail of an ORM and defeats the spirit of using the Repository: tell the Repo what you want from it, not how. IQueryable means you are building part of the query yourself thus you tell it how.

The generic repository is mostly an anti-pattern, as it uses the ORM entities instead of Domain entities. Even using DOmain entities, it usable only as Domain Repositories, because you need a different interface definition for querying purposes. DEfine each repository interface as you need it.

About pagination, just pass 'skip' and 'take' arguments to the repo method.It will work even if you don;t use an ORM, the repo will implement the pagination according to the DAO it uses to work with the db. And for your own good, try employing the CQRS mindset, it will make your DDD life much easier.

Upvotes: 1

Related Questions