12/16/2008

LINQ To SQL / Entity Framework / NHibernate ORM Top-Down, Objects First

People demand freedom of speech as a compensation for the freedom of thought which they seldom use. – Soren Kirkegaard

In the process of stumbling through LINQ To SQL to see if I would be able to represent a SQL Server database schema I created to provide storage for a hierarchical well-defined XML Schema for a commonly used utility object, I came to the realization that I was indeed doing everything completely backwards!

What I am saying is this:  ORM should be done by focusing on the OBJECTS FIRST, not the Database Schema! Unfortunately, most of the tools we have are data-centric, not object-centric.  Scott Allen has a post that clearly describes the debacle.

To my knowledge, there will not be any plain old CLR objects (POCOs) in Entity Framework. LINQ to SQL doesn’t yet have all the mapping capability to really separate the object model from the underlying database schema – and of course, you can use it with SQL Server only.

Now, this situation may improve in the future. But hey -- I need to write this application now, and I’m not about to hold my breath waiting.

Of all the .NET frameworks out there (including the current Microsoft offerings) the only mature offering that appears to be really capable of providing the mapping functionality I need is NHibernate. With NHibernate, I can create my objects (classes) first, create the mapping schema, and then using the SchemaExport class to create the matching database schema. Best of all, NHibernate is happy whether you do this with SQL Server, Oracle, or even SQLite.  Pete Weissbrod has some excellent material that you can use as a study guide on how to do this.

The key feature with an ORM like NHibernate is what's called transparent and automated persistence:

A DataSet allows you to extract the changes performed on it in order to persist them. NHibernate provides a different feature: It can automatically persist your changes in a way that is transparent to your domain model. This means a complete separation of concerns between the persistent classes of the domain model and the persistence logic itself, such that the persistent classes are unaware of—and have no dependency to—the persistence mechanism.

An “Item” class, for example, will not have any code-level dependency to any NHibernate API.  It doesn’t need funky attributes on the class or methods that can make serialization and re-use over the wire via WCF difficult. In addition,  NHibernate doesn’t require that any special base classes or interfaces be inherited or implemented by persistent classes, nor are any special classes used to implement properties or associations.

The bottom line for me is that in a system with transparent persistence, objects aren’t aware of the underlying data store; they need not even be aware that they are being persisted or retrieved. They can be serialized, sent over the wire, used for NUnit Tests, and more.

As Scott indicates in his post, developers need to learn how ORM identity maps work. Think objects first, data second. Start with your classes and business logic, and only then get the persistence and mapping to the database done. It was a hard lesson to learn because I’ve wasted a lot of time, partly because of a predilection for using the Microsoft flavor,  but now I think I can safely say that “I got it”.