Los Techies : Blogs about software and anything tech!

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.

Kick It on DotNetKicks.com
Posted Sep 02 2009, 09:00 PM by bogardj

Comments

Eyston wrote re: DDD: Repository Implementation Patterns
on 09-02-2009 11:40 PM

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<T> 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 :).

Nicholas Blumhardt wrote re: DDD: Repository Implementation Patterns
on 09-03-2009 1:13 AM

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:

ubik.com.au/.../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

Think before coding wrote re: DDD: Repository Implementation Patterns
on 09-03-2009 3:00 AM

My preference clearly go to the third option, specific repositories.

But implementation behind the interface is served by a generic Repository<T> class.

This way I have strong repository interfaces that show clearly their capabilities, but easy implementation.

Reflective Perspective - Chris Alcock » The Morning Brew #425 wrote Reflective Perspective - Chris Alcock &raquo; The Morning Brew #425
on 09-03-2009 3:19 AM

Pingback from  Reflective Perspective - Chris Alcock  » The Morning Brew #425

superbecio wrote re: DDD: Repository Implementation Patterns
on 09-03-2009 3:53 AM

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

DotNetShoutout wrote DDD: Repository Implementation Patterns - Jimmy Bogard - Los Techies
on 09-03-2009 7:20 AM

Thank you for submitting this cool story - Trackback from DotNetShoutout

Daniel wrote re: DDD: Repository Implementation Patterns
on 09-03-2009 8:57 AM

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<Customer>).  Creating, say, a EntityFrameworkRepository or NHibernateRepository would mean also changing the entity.

Eyston wrote re: DDD: Repository Implementation Patterns
on 09-03-2009 10:16 AM

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

bogardj wrote re: DDD: Repository Implementation Patterns
on 09-03-2009 2:10 PM

@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.

bogardj wrote re: DDD: Repository Implementation Patterns
on 09-03-2009 2:11 PM

@Nicholas

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

bogardj wrote re: DDD: Repository Implementation Patterns
on 09-03-2009 2:13 PM

@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 wrote re: DDD: Repository Implementation Patterns
on 09-03-2009 2:32 PM

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).

Nicholas Blumhardt wrote re: DDD: Repository Implementation Patterns
on 09-04-2009 3:03 AM

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

9eFish wrote DDD: Repository Implementation Patterns - Jimmy Bogard - Los Techies : Blogs about software and anything tech!
on 09-04-2009 3:53 AM

9efish.感谢你的文章 - Trackback from 9eFish

Nikola Malovic wrote re: DDD: Repository Implementation Patterns
on 09-05-2009 2:51 AM

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<T> usage I’ve seen on the net usually look more like generic Data Mapper then repository.

Nick Drew wrote re: DDD: Repository Implementation Patterns
on 09-08-2009 9:13 AM

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

#.think.in wrote #.think.in infoDose #42 (3rd September - 10th September)
on 10-02-2009 9:30 AM

#.think.in infoDose #42 (3rd September - 10th September)

lilikindsli wrote re: DDD: Repository Implementation Patterns
on 10-04-2009 7:47 PM

Rc9SEY I want to say - thank you for this!

Add a Comment

(required)  
(optional)
(required)  
Remember Me?

Enter the numbers above:
Copyright Los Techies 2008, 2009. All rights reserved.
Powered by Community Server (Commercial Edition), by Telligent Systems