Friday, July 27, 2012

Adventures in repository land

My original Entity Framework repositories sucked.  No, they really did.  They were bloated, ugly things, each tied to a particular type, and filled with repetitious code that was far too application specific.  I mean, look at this crap:

To be fair, the code above was one of my first iterations of a repository, written before I was comfortable with C# and EF.  That said, the recent iterations of my standalone repos weren't much better.  A whole bunch of inflexible, type-specific code.

I knew that the ideal solution would be to make my repositories as generic as I could (code to an interface, not an implementation, right?), but the existing Game repo had specific functionality not shared with the others, and, more importantly, it required the eager loading of related data, and I wasn't sure how I'd tackle that, or if it was even possible.

IObjectSet does not have the Include() method, and I thought I was sunk until I found this old blog post from Julie Lerman.  IObjectSet implements IObjectQuery, which meant that I could write my own extension method that (for all intents and purposes) overloaded Include().  Problem solved in a decidedly C# way.

So, behold my generic repository, and my Game specific subclass:

Now, what about my Game-specific code?  Simple:

When I need to do the extra Game-related things, I simply cast (canned example):

I'm not sure if this is the most elegant way to go about it.  The cast strikes me as a bit of a code smell, but since those methods are used sparingly in my project, it seems like it's good enough.  Most importantly, my code footprint has been significantly reduced, and my backend is far simpler than it was originally.

You may have noticed that my type parameters implement IHGEntity.  That's just a utility interface that allows me to access to my types' ID property, which in turn allows me to save my entities.  It is an epic one-line interface:

So, there it all it is.  I hope this will be of help to those just starting out with EF.

NOTE: Apologies for the inconsistent capitalization of type parameters in the code blocks above.  The synax highlighter is automatically making anything within angle brackets lowercase.