Since we are now able to use NHibernate at my current job, I decided I needed to alter my blogging strategy a little bit. It was my intention to demonstrate Allors in a couple of posts during which I would build up an invoicing application. Since I will have to do some learning of Nhibernate (reading the book 'Nhibernate in Action'), I decided to build the same application in NHibernate as home practice. This way I can see what the strong and weak points of both the frameworks are create a good comparison between them.
Let's go high level and write down the differences I can spot immediately without an in depth knowledge of NHibernate.
What is Allors
Allors is not a pure mapper tool, it is a 'Domain Driven Enabler'. Your domain will be modeled (by using a "repository explorer") into a meta domain. This results in having full control of all your complete domain information both at runtime and design time. This meta information will be used to generate a database scheme for you (if you decide to deploy to a database, you can work completely in memory as well).
All access to class variables goes through strategy objects. These strategy objects are shielded from your domain class by means of Allors base classes (generated for you from the "repository explorer"). Your domain is thus heavily tied to the Allors platform. All objects are completely managed, they are created within a session which acts as a unit of work/Identity Map that can be committed/rollback entirely.
Allors tries to make relationships first class citizens into the development process. A relation should be considered as important as an object because a lot of what your object can or can't do depends on having such a relationship. (For example consider a relation between a person and a email. If that relation does not exists then the person cannot be emailed and a 'SendEmail' method on the object would make no sense). Every relation between objects is completely managed, all relations are by default bi-directional and both ends of it are maintained by the platform (see later 'what I like about Allors).
Allors chooses to not give the developer all the options. All the objects are loading with their value objects in them, in their strategy object that is. Once you need a relation to another object that object (or many objects depending on your relation cardinality) is lazy loaded. All access to variables is delegated to the strategy objects. There the lazy loading can be initiated if possible (lazy loading is possible if your strategy is based on a database, if the strategy is disconnected you might nog be able to load it afterwards), nothing happens through code manipulation or reflection.
What is NHibernate
NHibernate's domain model has no links with other assemblies what so ever. This is keeps your domain model lean and mean and involves no learning curve to build up your domain. However persistence is handled through mapping files/attributes. You can specify a ton of properties in here so it will take time to get this tweaked and completely learned. The major benefit of this NHibernate is that it can work with both existing databases as newly created (your ddl can be generation from Nhibernate).
Focus with Nhibernate lies towards mapping your domain objects into your database. It is focused on the object themselves and how to get them persisted into a database. All the rest is just standard behavior of .Net, meaning that a bi-directional relation is considered as two separate ones. You have to keep your domain in sync yourself.
As already mentioned NHibernate lets you specify the mapping between your object and your tables. While doing so you have a ton of options you can set. Different fetching strategies, Caching, setting variables through reflection (not exposing anything you don't want)... All is possible. It uses interceptors and code emitting to get all these things done without letting the persistence code into the domain. To do this you have to take some things under consideration (always create default constructor, make properties virtual in order to have them lazy loaded, ...). What ever happens with a sealed class??
High level Comparison Table
|Persistence Ignorant||Managed Object|
|Object Driven||Relation Driven|
|Lots of configuration and fine tuning possible||Defaults by Allors|
|Both New and Existing database schemes||Only Managed by Allors|
What I like about Allors (compared to NHibernate with my current knowledge)
Check the following code: Your domain model has two objects. A Person and an Address, the relationship between these two is a one-to-one, meaning that any address can be used for one person and one person can have only one address. Some code:
1 Person person1 = new Person(); 2 Person person2 = new Person(); 3 Address address1 = new Address(); 4 Address address2 = new Address(); 5 6 person1.Addresss= address1; 7 person2.Addresss= address2; 8 9 // Switch one-to-one relation 10 person2.Address = address1; 11 12 // Check that managed objects are correctly relinked 13 Assert.IsFalse(person1.ExistAddress); 14 Assert.IsFalse(address2.ExistPersoon);
The above test would go green with Allors, but with I don't know what happens with NHibernate. It will mostly depends on the mapping configuration you have specified. If you make the FK index unique I think you will get a FK Constraint violation?? If you don't make it unique your domain model will go out of synch with what you are trying to do/or you would have to get the objects in memory en remove the associations from them. I'll be doing a little spike in order of how these situations reaction (Still have to look into all the configurations possible before I can do that).
Where do we go from here
The next blog post will handle about the domain I will be building in order to make an adequate and more in depth comparison between both frameworks. The domain model will be about an invoicing application build in the simplest of way. That way I can as well check how future proof both frameworks are when you want to extend/update your database schemes and do some refactorings.
See you next time.