I got asked today what I considered in choosing NHibernate or Entity Framework. This is a modified version of my response.
Both are object relational mappers capable of working with POCO objects, ie objects that are built without any dependencies on their persistence store.
As ORMs, they implement Unit of Work, Repository and ObjectQuery patterns (see Fowler PPoEA). They resolve entity relationships and they both enable the mapping of type heirachies using Table per Hierarchy (TPH), Table per Class (or join subclass) (TPC) and Table per concrete type.
Entity Framework out of box does not support databases other than SqlServer|Express|CE. There are third party drivers available for other databases such as Oracle and MYSQL.
NHibernate out of box provides supports for SqlServer|Express|CE, Oracle, MySQL and many others.
NHibernate provides support for caching of entities, which is useful for global reference data or long running session scenarios. This caching is provided through pluggable providers, a number of which are provided with NHibernate and can work with SqlServer broker in a similar manner to a sql cache dependency.
Entity Framework supports a database-first approach with an integrated designer for Visual Studio. This designer produces an XML file (EDMX) that describes the required mappings. The designer does not accommodate for the full range of mappings possible, which leave you having to deal with the somewhat cryptic XML file directly, parts of which can be safely edited without being overwritten by the designer.
The build action on the EDMX file is to generate the entity classes. The big improvement on EF 4 is that the t4 to create the classes is easily modified to produce the classes you want.
My personal opinion is that designers are more often a curse than a blessing, particularly for application of any real complexity. An IDE upgrade may be impossible, or you might modify the underlying XML file in such a way that it never works again, or perhaps the designer is just too sluggish. I don’t rate designers too highly.
The alternative to Database-first development is model or code first. In this mode, domain entities are coded and their relationship to underlying database tables described using either declarative attributes or a Fluent API. I have discussed the configuration of Entity Framework CodeFirst here. As a general rule, I would avoid using declarative attribute to define database mappings as this is coupling your entities to the persistence store.
There is no code generation with NHibernate. Instead you have write your domain classes and use XML files to describe how the database tables relates to the domain entities. These XML files are then read from a location or as a embedded resource by NHibernate at runtime to create the mappings. The XML schema is not that difficult to understand but being XML is feels a bit, say 2003 rather than 2011.
So these days most folk seem to be using FluentNhibernate. This is an open source companion project to NHibernate and enable the use of compile-time safe Fluently coded mapping classes to describe eahc classes mapping. An interesting feature of FluentNHibernate is the Automapping features, which uses conventions to map tables to classes without the need for any configuration by the developer.
Entity Framework does not support mapping to enums or other custom types. Database fields must map to scalar primitive .net types. NHibernate supports custom types through the IUserType interface.
Entity Framework has a smaller API than NHibernate and exposes less knobs and levers. For that reason, it is probably easier to “learn” but when you need greater control then the limitations of the API quickly surface.
NHibernate has many points for extensibility for example:
- In the construction of the connection, which can be useful to set user session variables in the database
- Caching, as already discussed
- Interception of queries, inserts, delete and updates
- Interception of object creation
- Diagnostic logging with log4net
To the best of my knowledge, Entity Framework does not have any of these extensibility points.
On the other hand, with a larger API comes a steeper learning curve. For example, the NHibernate Session has the following methods: Save, Update, SaveOrUpdate, SaveOrUpdateCopy, Replicate and Merge, some of which have overloads that return different types.
Lazy or eager loading is a huge consideration, particularly with n-tier applications. Eager loading can kill you because you end up sucking down the whole database in a single call, but lazy-loading can leave you with n-select performance issues. Entity Framework feel really immature in this regards because you can only set the lazy loading behaviour for the entire context, not one an relationship by relationship basis. With NHibernate, you can configure the container so that parent objects are eager loaded and child collection are lazy-loaded, or mix it up to suit each case.
NHibernate allows greater specification of loading strategies. You can eager load using a join in an initial query or a subsequent select, and even the specify an optimal batch size on a select. None of these features are available with Entity Framework. A sub-select strategy is useful for preventing unnecessary queries for objects that are already in the session ,and is something evaluated on a case-by-case basis.
Both Entity Framework and NHibernate support Linq, although the implementation is different. In Entity Framework Linq queries against the database contact are passed to the native SQL linq provider while NHibernate Linq is translated into HQL or criteria in the session to create the sql. From an API perspective the feel is more or less the same.
In addition to Linq, NHibernate provides a QueryByObject API in which you pass in a object with properties you want matched set, and two other criteria APIs – ICriteria and HQL. With the multiple APi available, my advice is to choose one and use it consistently, preferably wrapped behind an application specific repository.
Another important area of difference is cascade specification and the attachment of detached entities. NHibernate allows you to specify whether a relationship should automatically cascade inserts, updates, deletes and deletes including orphins. EntityFramework on the other hand only allows you to turn the cascade delete specification on or off. In attaching detached instances, which is done in n-tier applications, NHibernate will automatically cascade the attachment of related objects and will perform the neccesary database queiers to work out what needs to be persisted to the database. EntityFramework will not cascade an attach, each relationship needs to be travsersed and attached explicitly. This is a bit cumbersome for large object graphs.
Both provide access to the raw sql connection for those cases where it is just needed.
Entity Framework, produced and supported by Microsoft has the advantage over NHibernate in terms of developers being able to find answers to questions. The MSDN documentation for Entity Framework is relatively complete and there are many technical evangelists espousing the use of Entity Framework.
NHibernate on the other hand has not got a corporate sponsor, and the quality of it’s documentation is definitely a pain point for developers learning NHibernate. A the time of writing, many google searches for NHibernate throw up their old JBoss site however the current “home” of NHibernate is http://www.nhforge.org. This fact alone throws a lot of developers.
As previously stated, the API for NHibernate has a lot more knobs and levers than Entity Framework, and I think for that reason alone much greater emphasis should be placed on getting the documentation right. I demonstrated before the large API for simply saving an object. It requires a lot a fair amount of pain and experience to know what eahc of them does.
Entity Framework is less mature than NHibernate, and I believe that it has a number of releases to go before it is enterprise feature-rich. Each release represents an opportunity for breaking changes, which is a consideration. Alternatively, Microsoft may not develop EntityFramework further which would be creating a potential legacy application. On the other hand, NHibernate is a community project and has to date been successful without a commercial imperative.
I’ve covered a lot of stuff here based on my own real-world experience with both Entity Framework and NHibernate in n-tier applications. In a few words, I would say that Entity Framework is easier to learn but harder to control and extend to a complex scenario, so as the complexity of the domain increases I would lean more and more towards NHibernate configured using FluentNHibernate.
In any event, I really want to stress the importance of separating the dependencies on the ORM from the application code, either through the use an IOC container or application interfaces. It may be that NHibernate is a better choice for complex applications at the moment, it may not always be that way.
I would also look at the development team. Frankly, working with an ORM and domain classes is a whole different kettle of fish to coding transaction-script style services and records sets. It’s taken to a whole new level when multiple tiers come into play. Some developers find the transition too much and that needs to taken into account when choosing a development approach. I would recommend finding a mentor that can guide the team through the pitfalls that most definitely exist.
Lastly, in addition to implementing a number of useful enterprise patterns, above all an ORM is about reducing the complexity of mapping a complex object domain to a relational database. If the project is simple to start with, with little or no object-relational impedance, an ORM will only introduce complexity where none was required for no perceivable benefit.