I’ve read a lot of blog posts about the Repository pattern. Whenever I have looked at implementing it, I always come away underwhelmed. It’s one of those things that displays nicely in a small example but in practice you end up with a huge number of methods that each query the data in a similar but slightly different manner, and for me it’s fault is with querying.
Now granted I made that last one up, but I have seen Repository examples that are nearly as silly.
The story is even worse when you are trying to bring back data in a form that does not exactly match your data structure. The pattern feels very restrictive to me with each repository matching an entity in the database.
LINQ is a tempting way of getting around the querying problems by exposing a LINQ provider for your datasource to the other areas of the application. Which in certain cases I am all for, but in a large enough application this really isn’t that different from just letting the business layer execute it’s own SQL. Sure you might get some strong typing, but a basic structure change in the database can still see you hunting all over for references that need fixing.
Then one day I saw in passing someone comment they preferred to use Query objects now over Repositories. A quick internet search didn’t turn up anything I considered a pattern so I set about thinking what might be meant by a Query object, and quickly convinced myself this is what I was really after.
The basic requirements I had were a data layer that worked with POCO objects, able to be created as an interface to allow a secondary implementation and a focus on usable querying for both straight entities from the database and ad-hoc queries as needed.
The objects I ended up with were fluent wrappers for basically a set of query options. These options are then used to construct a query using whatever method of database connection the app is using. Here is an example of a query to give you an idea of how it works.
And here is an example of how to implement FirstName_Contains() in an implementation of the query layer that uses NHibernate.Linq as it’s data provider.
Obviously that implementation code depends heavily on how you talk to your database. Before I started to utilise NHibernate.Linq it looked more like this
So I now use a single database object that can load and save an entity from any table in the database, and it can also set up a query object for me to fill out with the appropriate options for that query and execute it.
I find this a nice middle ground between needing every query to have it’s own method and the open slate that comes from exposing a LINQ provider or SQL statements.
I won’t pull apart one of the projects that uses this to offer a full example of every method, but it is simple to add features like Top(), Take()/Skip(), even Count().