This is a bit of a ‘me too’ post… Reason for posting this is it continues the story of building an application. Also, I will be posting up how I extended the caching aspect to support caching for entity framework (this wouldn’t make sense without this post on the repository). Caching is not currently supported by Microsoft so you have to roll your own (this is a shame because other ORM frameworks do support caching). More on that later. It also shows why the object lifecycle and guaranteed disposal was so important (solved by Windsor Lifestyles, as per my posts on WCF and NServiceBus per message lifestyles).
This post doesn’t just cover the repository pattern, it also shows the specification and unit of work pattern in use. The specification pattern is actually described in tandem with the repository pattern by Martin Fowler.
Entity Framework 4.0 supports POCOs (plain old CLR objects). Right now our project isn’t using this. The project was already underway and using EF and I see no reason to change anything right now. I would probably have chosen NHibernate over entity framework, but that’s my personal preference. To be honest Entity Framework 4.0 is much better than the previous version. This isn’t a debate about which is better. But, if a repository pattern is used you could (if you wanted to…) change. With that in mind:
These interfaces don’t know about entity framework. They define queries as LINQ specifications so as long as the implementation supports LINQ then you’re all good. I guess there is an IRepository which has no LINQ stuff that this could implement, but right now I don’t need it. There are a few things on the repository that were added later to support some stuff I needed to do with caching, hopefully become clear later.
The entity framework implementation looks like this:
If you’re wondering what Lock is I’ll show that later. That might be controversial, but it solved a problem for me…
Before we look at the implementation of session let’s have a look at a concrete repository.
The repository some how needs to create a ObjectContext. You can’t (or at least I’ve not found a way) work out what object context an entity is related to. The CreateSession method enables us to say what the context is, this is done once, so you have a base repository per object context.
The session itself is shared between repositories. Its lifestyle is managed by the container. This means lots of repositories can perform CRUD operations but you can ask the session to save all changes at once. Thus, a single transaction. This also means that objects do not need to be repeatedly fetched from the database. Lazy loading just works in classes which have no knowledge of the repository (the behaviour is kind of like an aspect). The thing I don’t like is having a SaveChanges method on the repository and I don’t like it because it implies that you’d just save the changes that the repository made – that’s not the case… Maybe I’ll remove it?
Here’s the session implementation:
The main thing to notice about the session is that when it is disposed it detaches all attached objects. I’ll explain this later when I talk about caching, but it was to solve a problem I was noticing when load testing my WCF services…
Here’s the repository in action in a unit test:
The specification looks like this:
One thing I like here is that there is no need to mention entity framework. The ISomeEntityRepository (it’s defined above, have a look) is not anything to do with Entity Framework and neither is the specification. They happen to use things which derive EntityObject but that’s it. If you were refactoring to use POCO’s then the usages wouldn’t break (as long as you don’t refer to properties which only exist on the EntityObject).