Wednesday, July 18, 2012

The problem with ORMs

pigdogOver the last 8 years I’ve done a lot of thinking and experimenting with different persistence models. If you’d asked me 6 years ago what a persistence layer should look like I would have whole heartedly suggested an ORM like nHibernate.  Linq to SQL came along and initially looked promising but I quickly soured on it in favor of Entity Framework.  Then I actually tried to use Entity Framework in a production app and quickly found that in spite of the initial query writing efficiencies, it caused problems in other areas and the net result was that it didn’t save me any time at all but did add limitations and complexity to my app. 

So what was the problem?  As I spoke with more developers I started to hear the same complaints, even though some were using EF, some were using nHibernate, others were using LinqToSql.  I heard the problem stated best by a guy I met at the speaker’s dinner for the Rocky Mountain Tech Trifecta.  I can’t remember the guy’s name but his words stuck with me. I was telling him that I would never use EF again if the choice was up to me.  He said it’s not that he has a problem with Entity Framework, it’s that he’s done with ORMs.  I think that’s really the heart of it.  There’s a fundamental problem with ORM as a pattern.  It just doesn’t adequately solve the problem and it ads significant complexity and inefficiency to an application.

I recently ran across a couple of old blog posts that make for interesting reading, Is OR/M an anti pattern? by Ayende, and ORM is an anti-pattern by Laurie.  I’m hearing this line of thought more often as more developers use EF and other ORMs in production apps and then have a couple of years of living with the consequences.

So it’s easy to knock something, but what’s the alternative? For me it’s been moving to a simpler data mapper instead of a full on ORM.  I first wrote my own simple data mapper, but since then I’ve discovered Dapper.net by Sam Saffron and Marc Gravel.  On the surface Dapper works almost identically to the mapper I wrote, but under the covers it’s way better and much more efficient. So I’ve been porting all of my old code over to use Dapper. 

The results so far have been fantastic.  Sometimes I have to write more code that I would have to write with a full-on ORM, but I find that I can make major application changes (relatively) quickly and easily and I have never once spent hours struggling with my persistence architecture trying to understand why I’m erroring out on an update for an object graph, or troubleshooting lazy load issues, or select N+1 issues, or thinking to myself “If only this was SQL I would know exactly how to do this”.  Instead it just works, exactly the way I expect it to, and in the end that saves a lot of time and effort.