Tagged with NHibernate
I like to write blog posts where I offer some pragmatic advice. In most posts I try to include tons of code samples and example projects...but this post is different. I am trying to get my head around something so I want to share what is in my head so I can get a conversation started with my readers to help me out. Once you read this post, please comment...
The other day I was responding to a tweet from Doug Purdy. He had posted a link to some new EF 4.0 features by the boss at Microsoft's DevDiv. I, as usual, complained instead of lauded the list. I started a conversation about lazy loading and the potential danger of it, but quickly Doug mentioned that ORM's maybe were the wrong approach in general. That got me thinking (not always a good idea).
UPDATE: I've confirmed that the NHibernateContext class supports the IUpdateable and IExpandProvider interfaces required by ADO.NET Data Services (I think these are the implementations I added in the NHibernateContrib tree some months back - (See IUpdateable Part 1, Part 2, Part 3 and IExpandProvider posts).
I've finally had a chance to update my Silverlight 2-ADO.NET Data Services example. In this new sample I show how to create a Line-of-Business application (an XBox Game editor) using ADO.NET Data Services against both an Entity Framework model and NHibernate. Unlike earlier examples, this one includes implementation against the ADO.NET Data Service Silverlight 2 library to support saving of changed entities. In addition, I show some techniques for paging, retrieving simple types over an ADO.NET Data Service and full styling of the application. I hope to add support for Forms Authentication in the coming weeks.
Feel free to post replies with questions about the sample.
It seems that because of some internal NHibernate changes that are required to make NHibernate LINQ work really well, the current version of NHibernate LINQ will not be supported. Evidently there are a number of complex queries that do not work correctly under the current codebase. Its been announced that these changes will be made in the NHibernate 2.1 (which is in development). Follow the link to read the full details!
Data is a funny business. While at the moment I am spending a lot of time teaching Silverlight, my passion still lives in the data. I was brought up on Minisystems (Multi-user CP/M and the like) where you were dealing with something like a database (though we didn't have that as firm a concept as you might think). Later I did quite a lot of desktop database development starting with dBase II (yes, I am that old), Paradox, Clipper, FoxPro and even Access. That naturally led to client-server and N-Tier development. Throughout all the time its become exceptionally clear how much data matters to most applications.
But using databases can be difficult as there is an impedance mismatch with object-oriented development and the natural structure of data. The solution to this for many organizations has been to build data access and business object layers around the data. These layers were meant to simplify data access for most developers and embed the business logic directly into a re-usable set of code instead of it ending up in the UI layer. This was a good thing...
But the problem is that much of the data access (and to a lesser extent, business object) code was very redundant. Developers ended up writing the same code or simply mimicking schema that was in the database. Some started to develop ways to use the database schema to their advantage to limit the amount of hand-written code was created. While not always called this, this is where object-relational mapping (ORM) products got their start.
UPDATE: I know the title is wrong and it should be IUpdateable but I didn't want to break any links for any RSS feeds that already had it.
In this final part of the IUpdateable implementation, we will discuss the rest of the methods which includes ClearChanges, ResolveResource, ReplaceResource, SetReference, AddReferenceToCollection, RemoveReferenceFromCollection and SaveChanges.
As part of my work on the ADO.NET Data Services support for NHibernate.LINQ I decided that we should support IExpandProvider as well.
Next Monday night (July 28th, 2008), i'll be giving the short Q&A session at the Atlanta .NET Users Group. The topic? NHibernate's LINQ and ADO.NET Data Services support. If you're interested in using NHibernate but don't want to give up your LINQ skills, stop by for a listen!
Now that my ADO.NET Data Services support has been merged into the trunk of NHibernate.LINQ, I do have some caveats about using NHibernate.LINQ with ADO.NET Data Services. ADO.NET Data Services is a beta 1 product so there are some bugs and issues that you will either need to avoid or work around.
The biggest issue is around entity identity. ADO.NET Data Services must know how identity is established for objects in order to support the Data Service. It does this in a two step process:
UPDATE: Looks like I uncovered a ADO.NET Data Services bug in FF3. The examples will only work with IE and Safari at the moment.
After a couple of weeks on and off the project, I finally finished the first stab at adding ADO.NET Data Services support to NHibernate.LINQ. To accomplish this I've added three features:
After spending time creating my own caches of reflection data I found the NHibernate type information to be more complete and faster. Go figure. At this point I am using the SessionFactory's GetClassMetadata and GetCollectionMetadata to return IClassMetadata and ICollectionMetadata interfaces. So far this has given me every piece of runtime information I need and means that I don't need to do any nasty (and potentially fragile) walking through the property interface of the context object. Whew...
So to refactor my GetResource and CreateResource calls. GetResource is easy. GetResource passes in the query and the full type name (though the full type name may be missing in some cases). The query it passes it must resolve to a single result. That means I can simply execute the the query and if it returns more or less than one result, return an error. Once I have the result I can just check it against the full type name (if it was passed in) and return the value.
I have been diving pretty deep into ADO.NET Data Services (see an upcoming article about ADO.NET Data Services and Silverlight 2 coming soon). I've been looking at the story around non-Entity Framework models through a Data Service and thought that NHibernate through a Data Service would be a great example.
So I tried to get it to work with the NHibernate LINQ project. The example model that the project uses is a simple Northwind model. I thought I'd just take that model and expose it via ADO.NET Data Services. I crufted up a simple Data Context object for ADO.NET Data Model but it didn't work. ADO.NET Data Services was complaining about the fact that the end-points (e.g. IQueryable<Customer>) was pointing at an Entity. This was a bug...a but in ADO.NET Data Services. I hacked together a fix to get around it (and reporting it). If you're interest, the problem is that if the key of the entity is in a base class and *not* named "ID", it fails to find it. Again, this is a bug not a feature of ADO.NET Data Services.
Now that it was working, now what? I wanted to be able to make changes to the model but the NHibernate context doesn't support the updating interface: IUpdatable. (Though I sure wish they'd rename it IUpdateProvider to match the IExpandProvider interface). If you're not familiar with this requirement, note that only the Entity Framework currently support the IUpdatable interface (and is in fact implemented inside of ADO.NET Data Services not directly in Entity Framework). This means that DataSets and LINQ to SQL do not support it either.