Is Implementing the ‘Repository’ Pattern Redundant When Using ORMs?

February 28, 2011 · 26 comments

in ASP.NET MVC,C#,LINQ,NHibernate

I originally posted this question on www.stackoverflow.com to get some feedback regarding the usage of Repository pattern in ASP.NET MVC 3 applications. I posited that the Repository pattern implementation was redundant when our application used LINQ with ORMs such as Nhibernate or Entity Framework Code First. Here I explain in depth why implementing Repository pattern is redundant in ASP.NET MVC 3 applications that uses Nhibernate 3.0 or Entity Framework Code First.

Repository Pattern as Defined

Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects.

Source POEE and DDD

Popular Implementation of this Pattern

Say we are developing a blogging application and we identify the following domain models,

public class Post
{
    //Post specific properties here.
}

public class Comment
{
    //Comment specific properties here.
}

//.... and other domain models.

One of the popular implementations of this pattern is as follows.

First a repository via interface is defined,

public interface IPostRepository
{
    void Add(Post post);
    void Update(Post post);
    void Remove(Post post);
    Post GetById(Guid postId);
    ICollection<Post> GetByCategory(string category);
}

public interface ICommentRepository
{
    void Add(Comment comment);
    void Update(Comment comment);
    void Remove(Comment comment);
    Comment GetById(Guid commentId);
    ICollection<Comment> GetByPost(Guid postId);
}

Then a concrete implementation. A possible Nhibernate implementation,

public class PostRepository : IPostRepository
{
    private ISession Session {get;set;}
    public PostRepository(ISession session)
    {
        Session = session;
    }

    public void Add(Post post)
    {
        using (var txn = Session.BeginTransaction())
        {
            session.Save(post);
            txn.Commit();
        }
    }

    public void Update(Post post)
    {
        using(var txn = session.BeginTransaction())
        {
            session.Update(post);
            txn.Commit();
        }
    }

    public void Remove(Post post)
    {
        using(var txn = Session.BeginTransaction())
        {
            session.Delete(post);
            session.Commit();
        }
    }

    public ICollection<Post> GetByCategory(string category)
    {
        return Session.Query<Post>()
            .Where(post => post.Category.Name.Equals(category)).ToList();            
    }

    public Post GetById(Guid postId)
    {
        return session.Get<Post>(postId);
    }
}

public class CommentRepository : ICommentRepository
{
    private ISession Session {get;set;}
    public CommentRepository(ISession session)
    {
        Session = session;
    }

    public void Add(Comment comment)
    {
        using (var txn = Session.BeginTransaction())
        {
            session.Save(comment);
            txn.Commit();
        }

    }

    public void Update(Comment comment)
    {
        using(var txn = session.BeginTransaction())
        {
            session.Update(comment);
            txn.Commit();
        }
    }

    public void Remove(Comment comment)
    {
        using(var txn = Session.BeginTransaction())
        {
            session.Delete(comment);
            session.Commit();
        }
    }

    public ICollection<Comment> GetByPostId(Guid postId)
    {
        return Session.Query<Comment>()
            .Where(comment => comment.PostId.Equals(postId)).ToList();
    }

    public Comment GetById(Guid commentId)
    {
        return session.Get<Comment>(commentId);
    }
}

And finally we use those repositories in our corresponding Controller classes – assuming we are using a Dependency Injection Framework to constructor-inject our dependencies – Repositories – into the Controllers.

public class PostController : Controller
{
    private IPostRepository PostRepository{get;set;}

    public PostController(IPostRepository postRepository)
    {
        PostRepository = postRepository;
    }

    [HttpPost]
    public ActionResult Create(Post post)
    {
        if(ModelState.IsValid)
        {
            PostRepository.Add(post);
            return RedirectToAction("Edit", post.Id);
        }
        return View(post);
    }

    //Rest of the CRUD controller methods
}

public class CommentController : Controller
{
    private ICommentRepository CommentRepository{get;set;}

    public CommentController(ICommentRepository commentRepository)
    {
        CommentRepository = commentRepository;
    }

    [HttpPost]
    public ActionResult Create(Comment comment)
    {
        if(ModelState.IsValid)
        {
            CommentRepository.Add(comment);
            return RedirecToAction("Edit", comment.Id);
        }
        return View(comment);
    }

    // Rest of the Comment CRUD action methods.
}

Redundancy in the Implementation of this Pattern

The Repository pattern implementation shown above doesn’t serve as a useful abstraction. This is mostly because the actual work of providing a mapping layer and a collection like interface is done by the ORM – NHibernate and LINQ respectively. The Repository pattern here mostly acts as a thin proxy to the actual implementation. Since the abstraction – IRepository implementation – isn’t useful it serves more as noise rather than a useful abstraction.

Furthermore, un-necessary code is being written without any realizable benefit – either developer productivity or product quality. Because the above pattern is prone to code bloat it also increases the possibility of defects in the software system.

Because the pattern also emphasizes repeatability – in the interface and then in the implementation – it is also prone to the side-effects of a less DRY code.

A Possible Alternative Implementation

One possible more DRY and concise alternative would be to remove the usage of interface inheritance pattern and use the facility and the API already provided for by the ORM framework. A possible alternative implementation for an ASP.NET MVC 3 application could be as follows,

public class PostController : Controller
{
    private ISession Session{get;set;}

    public PostController(ISession session)
    {
        Session = session;
    }

    [HttpPost]
    public ActionResult Create(Post post)
    {
        if(ModelState.IsValid)
        {
            Session.Save(post);
            return RedirectToAction("Edit", post.Id);
        }
        return View(post);
    }

    public ActionResult Index()
    {
        return View(Session.Query<Post>());
    }
}

Summary

The reason for emphasizing on the conciseness of the codebase is because a concise, DRY code is less prone to defects, i.e. the more you can write the least possible lines of code the less chances you have of introducing *defects and or bugs in your software system.* The implementation of the Repository pattern as outlined above adds to the verbosity and code bloat of the system without any realizable technical benefit.

  • Claudia von Furstenberg

    Dude, you’ve got me intrigued.

    Could you show us your definition of the ISession interface and a sketch of its implementation, i.e. public class Session : ISession?

    • Bikal Gurung

      @Claudia,

      ISession is a NHibernate Session API interface. The concrete implementation is provided for by the Nhibernate itself. To use it we just need to declare it. In my sample I am assuming that we are using some sort of dependency injection framework to inject the concrete implementation of ISession.

      • FeedYourHead

        If you are not taking a pluggable DAL into account, why would you use dependency injection instead of just initializing stuff in the dependent code…?

  • http://pyrotheprogrammer.wordpress.com Daniel Powell

    How do you implement getting by foreign keys and other more complex thing than just by the primary key without repeating that logic all over the place?

    • Bikal Gurung

      From DDD perspective, you might want to group the business logic in the Domain objects/classes themselves. For example given entities blog post and comment, one possible way to implement foreign key mapping would be as follows, assuming you are using Enttity Framework 4.1,

      public class Post {
          public ICollection<Comment> Comments{get;set;}
      }
      
      public class Comment{
          public Post Post{get;set}
      }
      
  • DavidS

    Very interesting post. Simple question for you. How would you implement unit tests without hitting the database as I don’t want to “pollute” the latter. Isn’t that a case where the repository pattern comes in handy?

    • Bikal Gurung

      If you want to unit test with the mocks, Mocking frameworks such as pex/mole makes it very easy to create mocks. However, from my experience I am not sure if mocking is a rigorous enough technique. For rigorous and robust testing, I tend to always use the actual database and set-up that I normally use for production. I have found that techniques such as mocking and using database that is different from production(e.g. memory only DBs) don’t uncover bugs/defects that you would normally get when doing unit testing.

      For example, one feature that comes to mind is the possible data mapping mismatch between mocks, memory only databases(Sql Server Compact) and MS SQL Server. The time datatype is not supported in SQL Server compact but is supported in MS SQL Server. If your eventual production environment is MS SQL Server and you are using SQL Server Compact then the test will not pass whereas in actuality it should/will pass if you were to use your production environment setting.

      Furthermore, I think it might help you if you do your unit testing via the Controller action methods.

      • Jonas Gauffin

        Using a DB is integration testing and not unit testing. You can’t really predict the result when using a DB unless you reset the contents between each test (= poor performance).

        Unit testing is not easy with this approach.

  • http://simplycode.net Omkar

    Interesting. How about having the Add,Update,Delete and GetById methods in a generic Repository. Having PostRepository inherit Repository and implementing GetByCategory and similar for CommentRepository. Would that not be DRY enough and a justified use of the Repository pattern along with ORMs?

    • Bikal Gurung

      Hi Omkar,

      Modern ORMs such as Entity Framework 4.1 and NHibernate already provide for the CRUD facility out of the box. See my code sample above to see a version with repository and without the repository. In addition LINQ makes querying pretty painless and intuitive.

  • Sudhir

    Bikal, I agree with the what you are trying to say throough this post. My concern => 1 Why to depend on ORM facility of CRUD ops? (Seperation of concerns need to be there in our data access code which will be becaz of repository pattern.) 2 It will be easy for unit testing the CRUD ops & be sure of that our data access code’s CRUD ops are working fine. What are your thoughts on this ?

  • James

    But then you’re tied down to your choice of ORM.

    By using the Repository pattern here, you’re taking control/ownership of the Repository interface. The implementation would then be ORM specific – e.g. could start out with NHibernateRepository and maybe if you choose to later go to EntityFramework, switch to an EFRepository. The client that uses the repositories then doesn’t need to be changed – still depending on IRepository, the DI container resolves it to your choice of implementation.

    That way, you’re flexible in choice of ORM without changing the client of the Repository layer.

    By going the repository way, you’re choosing to favour flexibility in this tradeoff.

    • Jonas Gauffin

      How often do you switch ORM in a project? I have never done that (but have switched ORM when starting a new project)

  • James

    Also, you could have defined a generic IRepository if all the repositories share similar functionality.

    • James

      IRepository<T> *

  • Joel Montealegre

    The repository pattern is more than just a thin abstraction. For instance, even the add method of a repository pattern which seems to be just a repetition is a good way of encapsulating of the ORM’s native implementation. It hides the complexity of trying to remember whether the method name is “add”, “insert”, “addnew”, etc. GetByKey Method is a good example of the abstraction because you don’t have to remember the actual LINQ syntax. In the future, if you decide to change ORM’s, you just have to change your repository base. ORM’s are fads, they change, and they upgrade. And when they do, I bet your repositories will still stay the same.

    The repository also patterns enforces SoC because it addresses the problem of persistence and domain logic separately. You can both test it separately.

  • E

    I am learning fluent nhibernate and using the repository pattern. It depends what you want to have the ability to swap out. If you want to swap out the ORM then the repository pattern seems really good.

    I have two dlls: the mvc3 app and one for data access, with the ORMs and entities too. In the data access dll I have a generic IRepository interface factory like this: public static class RepositoryFactory {

        public static IRepository<T> GetRepository<T>()
        {
            return new FNHibernateRepository<T>();
        }
    
    }
    

    The app dll never has to see which ORM the data access is using.

    • Anonymous

      Swap out ORM? Rubbish ! Any ORM you use, you use much more functionality than just the repository. What about the configuration, custom query language for that ORM, mapping logic etc. Do you seriously think switching ORM is just switching a repository? Incredulous.

      • E H

        All of the stuff that is specific to that ORM is hidden behind an interface. Bellow is what i’m using now, it’s one of those common design patterns (forgot the name). The app gets a repository by newing up a Repository instance. The specific ORM is specified in the line that reads: ActualRepository = new FNHibernateRepository(); in the Repository class contructor, so that is what you would change if swapping out the ORM. All ORM functionality and config is hidden behind this interface and the app/client never sees the name of the ORM being used.

        public interface IRepository<T>
        {
            void Save(T entity);
            void Update(T entity);
            T GetByID(int ID);
            T GetByID(String ID);
            IList<T> GetAll();
            T GetByName(String Name);
        }
        
        public class Repository<T> : IRepository<T> where T:class
        {
            private IRepository<T> ActualRepository;
        
            public Repository()
            {
                ActualRepository = new FNHibernateRepository<T>();
            }
        
            public void Save(T entity)
            {
                ActualRepository.Save(entity);
            }
        
            public void Update(T entity)
            {
                ActualRepository.Update(entity);
            }
        
        
            public T GetByID(int ID)
            {
                return ActualRepository.GetByID(ID);
            }
        
            public T GetByID(String ID)
            {
                return ActualRepository.GetByID(ID);
            }
        
            public IList<T> GetAll()
            {
                return ActualRepository.GetAll();
            }
        
            public T GetByName(String Name)
            {
                return ActualRepository.GetByName(Name);
            }   
        
        }
        
        • E H

          So swapping out would require writing a repository implementation to replace FNHibernateRepository above, including all config and everything. That might be really easy for instance if you are switching to an object database!

  • Maciek

    Look here: http://www.youtube.com/watch?v=PqaOxRbQmAQ&feature=related

    Ayende is talking about the repository pattern

  • Tony

    Your alternative is bad because there is no way to unit test your controllers without actually calling the database because your controllers using the ORM directly. Also, if you have to change ORMs for whatever reason, you will have to make the change in ALL of your controllers. If you put the ORM code in a repository, you only have to make the change in your repositories leaving your controllers untouched.

    • Anonymous

      No way to test your controller? That is not correct. You can always test your controller simply by instantiating it in your test classes and calling the controller methods as you would a normal class. See this link for one way of testing your controllers …

      http://www.asp.net/mvc/tutorials/creating-unit-tests-for-asp-net-mvc-applications-cs

      • Jonas Gauffin

        You didn’t address what he said. He said that there is no way to test the controller WITHOUT a database since you are using the ORM directly in them.

  • Tony

    A middle ground could be to use a generic repository to abstract the ORM code away from the controllers.

    • Anonymous

      Having a generic repository over another repository is a worse choice than using the repository in the first place. That choice provides no real benefit in terms of code quality or conciseness. In addition that abstraction serves no purpose and acts more as noise and technical debt than a useful abstraction.

Previous post:

Next post: