Generic repositories – A silly abstraction layer

This post is all about GENERIC repositories as in Repository, not about all types of repositories. Repositories are a great way to abstract away the data source. Doing so makes your code testable and flexible for future additions.

My recommendation is against generic repositories, since they don’t give you any additional value compared to regular repository classes. “Regular” repositories are usually written specifically for the requirements that your project have.

Let’s look at what generic repositories give you:

You can change OR/M implementation at any time.

Seriously?

  1. If you find yourself having switch OR/M during a project you have not done you homework before you started the project.
  2. The OR/M choice doesn’t matter since you have abstracted away the features of the chosen OR/M

imho you’ll stick with one OR/M during a project and switch for the next one (if you have to switch).

You have to write less code.

Here is a Generic repository (nhibernate implementation) from a SO question:

public interface IRepository<T> : IQueryable<T>
{
  void Add(T entity);
  T Get(Guid id);
  void Remove(T entity);
}

public class Repository<T> : IQueryable<T>
{
  private readonly ISession session;

  public Repository(ISession session)
  {
    session = session;
  }

  public Type ElementType
  {
    get { return session.Query<T>().ElementType; }
  }

  public Expression Expression
  {
    get { return session.Query<T>().Expression; }
  }

  public IQueryProvider Provider
  {
    get { return session.Query<T>().Provider; } 
  }  

  public void Add(T entity)
  {
    session.Save(entity);
  }

  public T Get(Guid id)
  {
    return session.Get<T>(id);
  }

  IEnumerator IEnumerable.GetEnumerator()
  {
    return this.GetEnumerator();
  }

  public IEnumerator<T> GetEnumerator()
  {
    return session.Query<T>().GetEnumerator();
  }

  public void Remove(T entity)
  {
    session.Delete(entity);
  }   
}

Take a look at the methods. All they do is to call methods in nhibernate. You do not win anything by doing so. All you get is an abstraction layer that removes the good things with nhibernate/ef/whatever.

It’s better to create a proper base class and move all repeated (DRY) functionality into it (and therefore still be able to take advantage of the features in your favorite OR/M).

Summary

Did I miss something that a generic repository gives you? Please make a comment.