What purpose does the Repository Pattern have?

I have watch Rob Conery’s great screencast about MVC Storefront. If you haven’t seen them, you should take a look. Really interesting, he build and app by using Agile, "TDD" etc. I have some comments about his implementation I want to share, and if you don't agree with me, it's fine, because I'm not an expert, this post is based on my own experience and knowledge ;)

Feel absolutely free to criticize me, but please give suggestions about what things can be done better, and also a reason why. There is no use if you add comments like "I don't agree with you!" if you don't say why.

Something that I don’t like with his implementation so far is his use of the Repository Pattern. I don't know what pattern Rob refer to, I assume it's Fowler's Repository Pattern. This post is based on my experience and interpretation of the Repository pattern, only so you know.

Rob creates a Repository which has a simple interface, he have for example a method GetCategories which returns an IQueryable<Category> object.

public interface ICategoryRepository
{
        IQueryable<Category> GetCategories();
}


He also use the Service layer to implement common used queries such as GetCategories.

public class CategoryService
{
    //...

    public IList<Category> GetCategories()
    {
        return _repository.GetCategories().ToList();
    }
}

Another method that Rob put in to the Service Layer is GetProductsByCategory(int categoryId).

This is the part I don’t like; I will try to explain why and based on my knowledge and experience of the Repository pattern.

The Repository has a responsibility to return entities. What Rod does is returning an IQueryable object, a query nothing else. So his Repository basically don’t return any entities, it’s when he first make a call to the ToList() he execute the query and then get the entities, but it’s the object he returns from the Repository that gives him the entities, not the Repository itself. For me the Repository he use is sort of meaningless; it only works as a query provider not as a Repository regarding to the definition of the Repository Pattern.


“The Repository will delegate to the appropriate infrastructure services to get the job done. Encapsulating in the mechanisms of storage, retrieval and query is the most basic feature of a Repository implementation”

“With a Repository, client code constructs the criteria and then passes them to the Repository, asking it to select those of its objects that match. From the client code’s perspective, there’s no notion of query “execution”; rather there’s the selection of appropriate object through the “satisfaction” of the query’s specification.”

“Most common queries should also be hard coded to the Repositories as methods.”

Source: PoEAA [Fowler] and DDD [Evans]


The interface of a Repository I should have used if I should slavery follow the definition of the Repository pattern is:

public interface IProductRepository
{
    //...

    public IList<Product> GetProductsByCategory(int categoryID);

    public IList<Products> GetProducts();
}


What infrastructure service the Repository should use  is something I will decide later in my project (This is also something Rob mention in his screencasts), first I will make sure my Domain Model is correct, then I decide based on my model what infrastructure service I should use to persist my model. The way to persist my model is something I probably never going to change, and to follow YAGNI which is a important part when working Agile, I shouldn't care or write code which make is possible to easy replace the infrastructure service a Repository use because I think it may change or I may need it later. But if I decide to use LINQ to SQL, the implementation of my Repository will probably look like this:

public class ProductRepository : IProductRepository
{
    public IList<Product> GetProductsByCategory(int categoryID)
    {
        using (MyDataContext dataContext = new MyDataContext())
        {
            return (from p in _dataContext.Products
                    where p.CategoryId == categoryID
                    select p).ToList();
        }
    }
}


Something to observe here is that I dispose the DataContext after I execute my Query. By doing that I will lose the track changing of my entities, my Unit of Work and also my Identity map which is handle by the Context. But when I write this code using Agile, I don't need it at the moment.

My Mock object for the ProductRepository would probably look like this:

public class MockProductRepository : IProductRepository
{
       public IList<Product> GetProducts()
       {
           var products = new List<Product>();

           for (int i = 0; i < 10; i++)
               products.Add(new Product(.....));

           return products;
       }


       public IList<Product> GetProductsByCategory(int categoryID)
       {
           var products = this.GetProducts();

           return (from p in products
                   where p.CategoryID == categoryID
                   select p).Single();
       }

       //...
}

 

If we return an IQueryable<> instead of a IList from our Repository and decide to use LINQ To SQL, we will need to have something in mind. Correct me if I'm wrong, but the GetTable method used by LINQ to SQL will return a Table<> object, which implements the IQueryable<> interface. The Table<> object will hold a reference to the DataContext. So a call to the ToList() method of the IQueryable<> require the context. So the following code will not work:

public class ProductRepository : IProductRepository
{
    public IQueryable<Product> GetProductsByCategory(int categoryID)
    {
        using (MyDataContext dataContext = new MyDataContext())
        {
            return dataContext.Products;
        }
    }
}


The implementation of the Repository can for example look like this to make it work:

public class ProductRepository : IProductRepository
{
     private MyDataContext dataContext = new MyDataContext();
     
     public IQueryable<Product> GetProductsByCategory(int categoryID)
     {
         return dataContext.Products;
     }
}


What does this code really do? Well it only expose Table<> objects at the moment and serve more like a query provider than as a Repository.

If we still keep this implementation we need to make sure the DataContext get disposed, so we don't add to much unnecessary entities to the Identity map etc, right!? This is something the Service layer need to do if we use the solution Rob uses in his project. If we don't want to reuse the same context for all method in our Repository we can use the following implementation:

public class ProductRepository : IProductRepository
{
    public IQueryable<Product> GetProductsByCategory(int categoryID)
    {
        MyDataContext dataContext = new MyDataContext();

        return dataContext.Products;
    }
}

 

The problem here is that each call to the Repository's methods, will create an instance of the DataContext which will be added to the memory, each will have it's on Identity Map etc, those features can probably be turned of so it will not be unnecessary copies of entities in the memory. But still I assume we need to have more things in concern when returning a IQueryable<>, maybe not at an early stage but later. Most of those can be avoided by not returning the IQuerable<>.

One last thing that I'm not a fan about is the following code:

return _repository.GetProducts.WithId(10).ToList();

It will break the Law of Demeter. Instead if we do a call like this:

return _repository.GetProductsWithId(10);

We will not break the law, and this is the kind of method a Repository should have, if the query of a products is a common query we need to use.

No one says that the Repository pattern Fowler and Evans talk about is a Silver bullet, and Rob has a good point when he told me:

“One thing I’ll suggest is that with a new feature set (.NET 3.5) comes some new ways of doing things.”

Even within the computer world, there are evolutions and we shouldn’t be afraid of changes and test new way to solve things.

It will be interesting to see how the final version of Rob's application will look like, maybe I will change my mind or his implementation will change ;)

Published Thursday, April 24, 2008 5:20 PM by Fredrik N

Comments

# re: What purpose does the Repository Pattern have?

Thursday, April 24, 2008 12:37 PM by Bertrand Le Roy

I have to say I quite agree with Rob: many of the design patterns need to be revised when something game changing such as Linq comes along. Linq frees the query language from the store's implementation and brings querying back from the depths of the DAL to the domain. And the way it's done (by deferring execution until we know as much as possible about the query and abstracting the low-level query), it's a good thing. The domain had to implement quasi-querying methods anyway every time, which we can now do away with.

You do raise good points about the data context, but maybe there's a way to solve those problems without throwing away the wonderful freedom that Linq gives here.

# re: What purpose does the Repository Pattern have?

Thursday, April 24, 2008 12:55 PM by Steve

Is some of this more an issue with how Linq to SQL was architected vs. the Repository pattern?

(PS. I think the Repository pattern is Eric Evans - DDD concept is it not?)

# re: What purpose does the Repository Pattern have?

Thursday, April 24, 2008 1:35 PM by Fredrik N

I’m too much colored by Domain Driven Design and the components used in DDD and have that thoughts in my mind. I’m also far away to even call myself an expert when it comes to DDD, I wonder how many people can say "I’m an DDD expert" ;)

Rob doesn’t claim that he even use Domain Driven Design, only the Repository Pattern and a service. But from a Domain Driven perspective (my interpretation), I will call his Service (current implementation of the service) for Repository, it fit so well in the description about what a Repository is and should work. What he calls a Repository, is for me a cool version of some kind of a pluggable provider and is created to make it easy to replace the infrastructure services his Service will use to get entities etc.  A Service for me should help with coordination’s etc. For example move money from one account to another one, that implementation should be in a Service. The Service can use the Repository to get the correct entity, and also update it and remove it etc. A Service can also be part of different layers, for example Application, Domain and the Infrastructure layer.

What I don’t like is that the word Repository Pattern is used in the context, when it only returns Query objects and doesn’t serve as a “repository” of entities. To change the Repository Pattern to be something different from what Martin Fowler and Evans describe it, is not fair. It’s like changing another pattern to be something else and copy the name, it will only confuse people. I would in this case give it a new name. I think Rob has invited a new and assume pattern when using LINQ, which shouldn’t be mixed with the name Repository Pattern. But that is what I think.

# re: What purpose does the Repository Pattern have?

Thursday, April 24, 2008 4:59 PM by Fredrik N

>"Linq frees the query language from the store's implementation and brings querying back from the >depths of the DAL to the domain. And the way it's done (by deferring execution until we know as much >as possible about the query and abstracting the low-level query), it's a good thing."

Part from the deferring execution, this is what I have done when using Domain Driven Design. But I define a Query by using a specification object, so I still define the query within the domain model, not in the data access layer (which doesn't really exist when using DDD). But to use separation of concerns, the query is passed to the Repository and it will handle the execution and delivery of entities.

But I can agree, with LINQ there comes new way to do stuff.. we got a new player in the field!

# re: What purpose does the Repository Pattern have?

Thursday, April 24, 2008 5:05 PM by Liam McLennan

I have no problem with Rob's implementation of repository. When using Linq-to-sql it makes sense to return queries instead of collections because it allows some powerful chaining options later (for paging and the like). The only difference between a query and an instantiated collection is that the query simply has not been executed yet.

# re: What purpose does the Repository Pattern have?

Thursday, April 24, 2008 6:13 PM by Fredrik N

Liam Mcennan:

It’s wonderful implementation, by all means. Maybe Rob’s Repository will end up to be an anti pattern, who knows. But by definition a Repository will do execution of the query and return entities, not query objects. Take a look at the following implementation:

Public interface ICategoryRepository
{
       IQueryable<Category> GetCategories();
}

public class CategoryService
{

   //...

   public IList<Category> GetCategories()
   {
       return _repository.GetCategories().ToList();
   }
}

If it instead should look like this:

public interface ICategoryQueryProvider
{
   IQueryable<Category> GetCategories();
}

pubic class CategoryRepository : ICategoryRepository
{
    private ICategoryQueryProvider _categoryQueryProvider;

    //..

    public IList<Category> GetCategories()
    { 
        return _categoryQueryProvider.GetCategories().ToList();
    }
}

Then the CategoryRepository by definition is a Repository.

# re: What purpose does the Repository Pattern have?

Friday, April 25, 2008 9:04 AM by BennyXNO

You raise a valid question. Why can't the repository do the listing of entities on its own and not reley on the Service. I feel the solution Rob has done is a nice one. What's the difference between IList and IQueryable is the question her. You can do almost precisely the same with both, the difference is more that IQueryable is a Proxy for IList so you get your Entities when needed. I don't feel that this violates DDD terms. I'm not the expert here but I feel that it's only syntatic sugar.

Your last comment gives a nice solution to the problem though and is maybe a better way to do it.

# re: What purpose does the Repository Pattern have?

Friday, April 25, 2008 10:46 PM by Steve

I switched back to NHibernate after using Linq to Sql.  

NHibernate integration with Spring.NET is a perfect fit.  I'd rather have Linq over NHibernate vs. Linq over Sql.  

# re: What purpose does the Repository Pattern have?

Sunday, April 27, 2008 4:51 AM by wwfDev

I agree with you Fredrik. In my opinion Rob's implementation has mingled layers and as I see it, it would cause trouble in an distributed environment. What if the consumer of his returned repository-query-objects resides on a different machine? What will happen when that consumer tries to query the resultset - I guess the DataContext will have some trouble accessing its source (or am I wrong here???)

# re: What purpose does the Repository Pattern have?

Wednesday, June 11, 2008 12:49 PM by Derek

Rob's repository makes more use of LINQ. Fredrik's is more classic and layering clear. Hope some giant can figure out a better Repository

# re: What purpose does the Repository Pattern have?

Wednesday, July 02, 2008 8:36 AM by Colin Jack

"change the Repository Pattern to be something different from what Martin Fowler and Evans describe it, is not fair."

I agree with all you've started and this statement in particular.

"Part from the deferring execution, this is what I have done when using Domain Driven Design. But I define a Query by using a specification object, so I still define the query within the domain model, not in the data access layer (which doesn't really exist when using DDD). But to use separation of concerns, the query is passed to the Repository and it will handle the execution and delivery of entities."

Amen to that, and if you want to chain them together chain the specifications (And/Or/Not) before passing them in (covered in DDD).

# re: What purpose does the Repository Pattern have?

Wednesday, July 30, 2008 7:28 PM by Altug

I very much like the CategoryRepository : ICategoryRepository implementation. CategoryRepository will also do things like add, update, delete. Now the client (a web page with a data grid) can grab the ICategoryQueryProvider from the service layer and do its paging, sorting on the client. I like a having a presentation layer with something like a CategoryPresenter class which can be used as ObjectDataSource. That class will expose Count(), GetCategories(int maxrows, int startIndex) and GetCategories(int maxrows, int startIndex, string sortBy) methods. This CategoryPresenter will grab the ICategoryQueryProvider in its ctor and the methods will make use of it.

# Pluggable Dependencies Intermission &laquo; Cav&#8217;s Weblog

Tuesday, September 02, 2008 6:33 PM by Pluggable Dependencies Intermission « Cav’s Weblog

Pingback from  Pluggable Dependencies Intermission &laquo; Cav&#8217;s Weblog

# Implementing a Customer Search Service with DDD, BDD and the Entity Framework &laquo; Cav&#8217;s Weblog

Pingback from  Implementing a Customer Search Service with DDD, BDD and the Entity Framework &laquo; Cav&#8217;s Weblog

# Implementing a Customer Search Service &ndash; Part 2 &laquo; Cav&#8217;s Weblog

Pingback from  Implementing a Customer Search Service &ndash; Part 2 &laquo; Cav&#8217;s Weblog

Leave a Comment

(required) 
(required) 
(optional)
(required)