Disclaimer: I am not an ORM expert. These tools have long learning curves and very few people could effectively provide adequate unbiased guidance. That said, I am going to try to provide guidance based on the research I have done. Your mileage may vary. This information is very time sensitive, these tools change rapidly and this information will likely be significantly out of date by the end of 2009. I have no vested interest in any of these projects.
First off, what is ORM? ORM stands for Object Relational Mapping.
For any given project that updates data in a database:
Should you use an ORM - Yes!
Should you build your own custom ORM from scratch - No!
Should you customize the ORM solution you choose - Probably
These aren’t even really controversial opinions. There was a time when ORMs weren’t mature enough to be “safe”, but that time has passed. The time saved by using an ORM is a no brainer decision.
There is even a pretty straight-forward answer to what .NET ORM you should be using:
The major advantages NHibernate has are:
- It's free (and open source)
- It can handle enterprise class ORM problems
- It has an active community surrounding it providing things it doesn't necessarily have “out of the box” like code generation and "convention over configuration"
- The majority of developer opinions regarding .NET ORM you will find on the Internet mention NHibernate
- It supports Linq (although not necessarily cleanly out of the box yet)
That isn’t to say that NHibernate doesn’t have disadvantages. In particular, the API can be difficult to work with. In reality, I believe any ORM capable of handling enterprise level ORM problems will have to expose a complex API and I believe that justifies NHibernate’s complex API to some extent. That said, there are projects surrounding NHibernate to expose simpler interfaces into NHibernate (more on a couple of those projects included below).
In the end, unfortunately in my opinion, simplicity is not something you really want in an ORM (I’m a simplicity nut, so this particular issue is very hard for me to cope with personally). The object relational impedance mismatch is a deceptively complex problem. Database performance is usually a very critical component of any non-trivial application. If you opt for a “simpler” ORM than NHibernate today, you may regret that decision tomorrow by underestimating your needs for an ORM.
That said, if you aren’t an experienced programmer, or you just can’t make it over the NHibernate learning curve, or you just don’t have enough time to work through the NHibernate ramp up process right now, there is a good alternative worth recommending.
Subsonic is a free, open source, "Microsoft subsidized" ORM that aims for simplicity of the API and definitely delivers on that front. It can actually handle many of the common use cases that are required of an ORM, but at some point you will fall off that “feature” cliff (for example: having to deal with a poorly designed database that you cannot change). You can be productive with Subsonic very quickly and it is very powerful.
Also, if you can’t use open source or would prefer a commercial product for whatever reason, LLBLGen Pro is worth recommending. It’s harder to find information about LLBLGen Pro since it’s not free, but it appears to be a quality solution. There is a fully functional 30 day demo available.
Microsoft has entered the ORM market recently with two products: LinqToSql and EntityFramework. While Linq itself is a wonderful step forward for pretty much all .NET developers, Microsoft’s ORM products are a major disappointment. While Microsoft has promised that EntityFramework will improve significantly with .NET 4.0, the evidence to back that up so far is not compelling. NHibernate seems to be way ahead of EntityFramework and as I mentioned above, it’s pretty risky to gamble on a “partial ORM” solution.
Thankfully, NHibernate and Subsonic support Linq, so you don't have to settle for Microsoft’s ORM tools (although I’m sure many projects will be stuck using Microsoft’s ORM, because it’s from Microsoft - I’ve been there personally and I’m sure I will be there again).
I mentioned above that you should probably customize/wrap your ORM of choice. Especially if you don’t choose NHibernate, I would work to isolate your ORM from the rest of your code base so you can swap in NHibernate later if necessary. While it’s possible that there are unit test generators for ORMs out there, I haven’t seen any and that seems like an obvious feature to have (generate basic unit tests for your basic data and business level objects based on the models exposed by the ORM). I like to have auto generated unit tests for my data and business layers as a confidence builder and as a base upon which to build more complex unit tests quickly. There are many other good reasons to wrap your ORM in a simpler, domain specific API.
The biggest issue with integrating an ORM is to make sure you have very clear separation of concerns. Your data layer should be the only layer with any exposure to a connection string. Your UI/Presentation Layer should not have any exposure to your data layer.
A very common temptation with ORMs is to use the “entity” objects they generate from the database model as your “business layer”, when that is really your data layer and you need to avoid mixing the two. Please resist that temptation. Unfortunately, there is a truck load of sample code available on the Internet that blatantly violates the separation of concerns concept.
People new to NHibernate (and ORMs in general) should probably look into using one of the following “helper” projects along with NHibernate to help with the ramp up.
(1) Fluent NHibernate
This will help generate the XML mapping files between your objects and database so you don’t have to write a bunch of XML by hand.
(2) Castle ActiveRecord
I recommend this project, but have reservations at the same time. The Active Record pattern can really help beginners, especially people new to ORM, get their head around how ORM works and why it’s beneficial.
It can also trap you in a box that is difficult to get out of, so I would recommend not getting too aggressive with the adoption of ActiveRecord until you have a good feeling for its limitations.
I would say start with ActiveRecord if you must, but get out of that box as soon as you can and once you have enough experience with the alternatives, you can more safely judge when ActiveRecord is the right answer.
While there are many alternatives to ActiveRecord, one of the more common alternative patterns is the Unit of Work pattern.
I share that just to provide additional information, you will probably not be able to apply either pattern as documented without bumping into their limitations eventually.
I spent quite a bit of time reading about many other .NET ORMs before posting this article, but for various reasons they weren’t included in the article. Some of the primary reasons for non-inclusion were:
(1) Lack of Linq support or lack of stated intent to provide Linq support
(2) Lack of recommendations from real developers while doing various Google searches
These seem like two pretty easy to apply criteria to separate “good” ORM from “bad” ORM (and there are a lot of bad ORMs - and I would hope most people try to code their own simple ORM sometime to help them understand how easy it is to create a bad ORM).
I would like to thank the following four bloggers specifically:
Ayende Rahien/Oren Eini, Rob Conery, Frans Bouma, and David Hayden
for their extensive writing on .NET ORM who helped frame much of what I have recommended in this article. Blogging about your ORM helps give confidence to those who want to use or recommend your ORM, so you will see a correlation between these bloggers and the tools I recommended.