DDD: Repository Implementation Patterns

One of the major structural patterns encountered in DDD (and one of the most argued about) is the Repository pattern.  You’ve created a persistent domain model, and now you need to be able to retrieve these objects from an encapsulated store.  In Fowler’s PoEAA, the Repository pattern is described as:

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

In many DDD implementations, the use of a Repository is widened to go beyond retrieval, but the other pieces in the CRUD acronym.  This is natural, as a Repository provides a centralized facade over some backing store, whether that backing store is a database, XML, SOAP, REST and so on.  But what about the actual interface of the Repository?  What kinds of options do we have for designing the actual Repository itself?  There are quite a few different schools of thought here, each with their own benefits and drawbacks.

The Generic Repository Interface

In the generic repository interface, the interface definition itself is generic, with implementations for individual entity types.  The generic type parameter denotes the entity type of the repository.  One example is in S#arp Architecture:

public interface IRepositoryWithTypedId<T, IdT>
{
    T Get(IdT id);

    IList<T> GetAll();

    IList<T> FindAll(IDictionary<string, object> propertyValuePairs);

    T FindOne(IDictionary<string, object> propertyValuePairs);

    T SaveOrUpdate(T entity);

    void Delete(T entity);

    IDbContext DbContext { get; }
}

If you want a repository for a specific type of entity, you create a derived type, closing the interface type with the entity:

public interface ICustomerRepository : INHibernateRepositoryWithTypedId<Customer, string>
{
    List<Customer> FindByCountry(string countryName);
}

Note that this repository supplies an additional, specialized query method for a specific find method.  The nice thing about a generic repository interface is that a corresponding base repository implementation can be designed so that all of the data access code that doesn’t change from repository to repository can have a place to live.  The actual implementation can then rely on a common base implementation for the non-changing behavior:

public class CustomerRepository : NHibernateRepositoryWithTypedId<Customer, string>, ICustomerRepository
{
    public List<Customer> FindByCountry(string countryName) {
        ICriteria criteria = Session.CreateCriteria(typeof(Customer))
            .Add(Expression.Eq("Country", countryName));

        return criteria.List<Customer>() as List<Customer>;
    }
}

But, we still get the type safety of generics.  However, we tend to muddy the contract of the ICustomerRepository a little if our entity does not support all of the operations of the base repository interface.  It’s basically a sacrifice of a common base implementation that you violate the Interface Segregation Principle for some simplification on the implementation side.  For example, in my current domain, deleting an entity has legal ramifications, so we basically don’t allow it for quite a few entities.  Instead, things are marked as various stages of “soft” deletes.

One big benefit is that most modern IoC containers allow configuring the container such that the most derived type of IRepository<T> can be resolved.  I can ask the container for IRepository<Customer>, and the CustomerRepository implementation is returned.  This is especially helpful in APIs where we might abstract “saving” to some base layer.  Again, the downside is that our interface has methods to support every operation, whether we actually want to support them or not.

The Generic Method Repository

In the generic method repository, our repository implementations do not expose methods for specific queries.  Additionally, no specific repository for an entity is defined.  Instead, only general-purpose methods are exposed for querying, persisting and retrieval.  The methods are generic, providing type safety, but there is only one implementation.  Consider the Alt.Oxite repository implementation from FubuMVC Contrib:

public interface IRepository
{
    void Save<ENTITY>(ENTITY entity)
        where ENTITY : DomainEntity;

    ENTITY Load<ENTITY>(Guid id)
        where ENTITY : DomainEntity;

    IQueryable<ENTITY> Query<ENTITY>()
        where ENTITY : DomainEntity;

    IQueryable<ENTITY> Query<ENTITY>(IDomainQuery<ENTITY> whereQuery)
        where ENTITY : DomainEntity;
}

In this implementation, the repository itself is not generic.  A single repository dependency can perform all needed CRU (not D) operations against any well-known entity.  Because most ORMs nowadays are generic, the implementation of a generic repository is very straightforward, it simply wraps the ORM.  The actual definition of queries is left to something else.  In the above case, LINQ queries utilize the Query method to retrieve persistent objects.

The advantage to this pattern is that we do not need to create an interface for each type of entity we create.  Instead, we remove the responsibility of forming specific queries to the callers, including worrying about fetching, caching, projection and so on.  Since this logic does not change, we don’t have to pull in a repository for every entity we want to retrieve.  Instead, operations flow through one general-purpose interface.

The disadvantage to this pattern is we lose named query methods on our repository, as Greg pointed out a while back.  The ICustomerRepository from the previous pattern exposed (and encapsulated) a well-known query with a intention-revealing name.  With a generic method repository, there is only one implementation.  Creating a derived ICustomerRepository of a generic method repository would be rather strange, as the base interface allows any entity under the sun.

The Encapsulated Role-Specific Repository

Classes that use a repository rarely use every method inside of it.  A class that does a query against Customers probably isn’t going to then go delete them.  Instead, we’re likely querying for some other purpose, whether it’s to display information, look up information for business rules, and so on.  Instead of a catch-all repository that exposes every method under the sun, we could alternatively apply the Interface Segregation Principle for role-based interfaces, and define interfaces that expose only what one class needs.  With these repositories, you’ll much more likely find encapsulated query methods, that do not expose the ability to arbitrarily query a backing data store:

public interface IProductRepositoryForNewOrder
{
    Product[] FindDiscontinuedProducts();
}

A single repository implementation implements all Product repository interfaces, but only the single method needed is exposed and used by the caller.  This way, you do not see Save, Delete, and other query operations that you do not care about.  The down side is that this implementation tends to be more difficult to combine with IoC containers, as auto-wiring does not work as expected.  At some point, it starts to look like these types of repositories are glorified query objects, a single class that represents a query.

Wrapping it up

In our projects, we’ve tended to use the generic repository interface, as it allows us to override implementations for custom behavior.  We still will include a default implementation that gets wired in, a non-abstract RepositoryBase<T>.  The IoC container is configured to pick the most specific implementation, but if one doesn’t exist, we don’t need to create a blank repository.  Sometimes, things like Save or Delete need to do custom things, and I’d rather put this in the repository rather than some other anonymous domain service.

In the end, it really depends on the situation of each project.  I’ve tended to stick with a generic interface, as it’s the easiest to scale complexity.  However, quite a few smart folks use the generic method repository, and rely on external queries for the hard stuff.  Complexity with saves and deletes is then handled by the cascading behavior of the underlying ORM.  It’s quite intriguing, but I’ve been reticent to give up a tried-and-true pattern.  I’m curious to see what other repository patterns people use out there.

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Jimmy Bogard

I'm a technical architect with Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.
This entry was posted in Domain-Driven Design. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Eyston

    So do you have the IoC auto wire the session for the Generic Repository Interface? I used to do this and found it kind of weird inside a UoW to call the repository without giving it a session. I know it was using the same session but it lacked explicitness.

    I gave up on repository and just use NH session for all Get / Load and Saves. It can be argued that session.xxx is a generic method repository yah? I lose any kind of ORM independence versus the generic method repository, but I don’t have a problem with that.

    In my current project I tried using Query objects from Ayende’s blog post. He news them up inside his controller code which is fine for him because he tests against a real session. I guess I’m a wuss and wanted to stub the query results for tests so didn’t find this method very enjoyable. I think query objects are the way to go ultimately, just figuring out the best way to use them :) .

  • http://blogs.msdn.com/nblumhardt Nicholas Blumhardt

    Hi Jimmy!

    I’m much in favour of the Generic Method-style Repository, but I can’t help piping up that there’s an awesome variation on this that you can use if your provider supports Linq:

    http://ubik.com.au/article/named/implementing_the_specification_pattern_with_linq

    When I wrote the article Linq was still fairly new and this was uncharted territory, but I’ve had good reports from others using this in production since then.

    Does this one get a name of its own in your taxonomy?

    Cheers!
    Nick

  • http://thinkbeforecoding.com Think before coding

    My preference clearly go to the third option, specific repositories.
    But implementation behind the interface is served by a generic Repository class.
    This way I have strong repository interfaces that show clearly their capabilities, but easy implementation.

  • superbecio

    I prefer the Generic Method Reporitory with a new layer up on it that exposes role based queries to business layer.

  • http://www.danielroot.info Daniel

    I’ll need to try this again, but last time I played with creating a Generic Repository, I was a little frustrated. Since ORMs then didn’t support POCOs, and each has its own flavor of attributes/mapping/etc., it ended up that the entity (ie Customer) was tightly coupled to one specific repository implementation (ie LinqToSqlRespository). Creating, say, a EntityFrameworkRepository or NHibernateRepository would mean also changing the entity.

  • Eyston

    Not sure why a DAL has to be ORM agnostic. It seems like a lot of work / over engineering for little practical benefit.

  • http://www.lostechies.com/members/bogardj/default.aspx bogardj

    @Eyston

    >So do you have the IoC auto wire the session for the Generic Repository Interface?

    yeah, and IoC also controls lifetime management. It’s not the session directly, but something like UoW.

  • http://www.lostechies.com/members/bogardj/default.aspx bogardj

    @Nicholas

    Nah, that’s still Repository! We use encapsulated query methods, but those queries could be HQL, ICriteria, or LINQ.

  • http://www.lostechies.com/members/bogardj/default.aspx bogardj

    @Eyston

    I don’t think it should be. How often do you really swap out ORMs, or databases? That’s one of those architecture decisions, hard to reverse and needs to be made very early.

  • Eyston

    I guess I’m lazy in that I use ISession as my UoW directly :) I have SM (IoC) manage that but decide I don’t like having the session plugged into several things per request. Now I generally try to structure things so that the object that initiates the UoW is the only one that is auto-wired a session and the UoW (session) is passed to any query object that needs it.

    I don’t know if this is valid, but I see parallels between Controllerless Actions and Query Objects (vs. a standard Controller and Repositories with custom query methods).

  • http://blogs.msdn.com/nblumhardt Nicholas Blumhardt

    @Jimmy I meant within your classifications of Repository types :)

  • http://blog.vuscode.com Nikola Malovic

    I am also in favor of 3rd option due to two main reasons:
    1) Ubiquitous language is very important part of DDD.
    FindDiscontinuedProducts is expressing a clear business case while FindAll(p=>p.productDiscount>0) does not.
    2) Domain logic in examples #1 and #2 could leak out to application\UI layer using the FindAll \ Query methods.In previous example, logic for what discounted product is inside the method, in second example (functions, dictionaries etc.) that logic is kind-a injected outside.

    IMHO, most an examples of an IRepository usage I’ve seen on the net usually look more like generic Data Mapper then repository.

  • http://pilchardfriendly.wordpress.com Nick Drew

    I think it’s important to recognise that you should tend towards one repository per-bounded context, not one repository per entity.

    So, having a ProductRepository make sense, say in a retail domain, where you may also have a SalesTransactionRepository.

    CustomerRepository makes sense, say, in an insurance domain, where you may also have a DocumentRepository (including Quotes and Policies).

    The tension comes when you need to cross the bounded context.

    If the current transaction is a call centre staff member searching for the quotes for a customer, it is entirely possible that I would use a specification pattern:

    documentRepository.getQuotes().SelectMany( q.insuredParties).Where( party.partyKey == currentCustomer.customerKey )

    However, if the context is finding all insured risks for quote, then I’d expect there to be something available on the repository for such logic:

    documentRepository,
    documentRepository.InsuredRisksForQuote( QuoteId )

    There are some things that are intrinsically part of the business processes of quotes, and should be first class elements of the domain. There are others that facilitate integration, and allow external specification. Defining bounded contexts helps decide when you should focus on one or the other

  • http://hammerproject.com matt kocaj

    @Nick Drew,

    Don’t you mean to say “one repository per aggregate” rather than “one repository per-bounded context”?

    Aren’t bounded contexts parent containers to aggregates and it’s possible to have more than one repo in a BC provided that there’s not more than one repo per aggregate?

  • Gustavo

    This is really bad…