Here is a very partial listing of features that I like in NHibernate.
- Change friendly - NHibernate make it very easy to handle changes, either in the mapping layer, or using 1:1 mapping to the database and asking NHibernate to create the database from the model or update the database schema to match the model. This means that making a change to the model is a very painless operation.
- Multi queries - the ability to batch several queries into a single database call makes for significant improvement in performance in almost any scenario.
That was actually a marketing feature, initially, but it turn out to be really useful.
- Future queries - building on the mutli queries capabilities, this allow you to retain a friendly synatx, but still get the perf benefits of multiply queries in a single remote call. Beside, you can now say that you are future proofing the application.
- Batch updates - and I am still bitter about SqlCommandSet being internal. That is a major annoyance.
- Caching - NHibernate has 4 different caches, the identity map cache is common in OR/M, but NHibernate manages a second level cache as well. Which can be turned on by a config setting, which allows you to cache just about everything. NHibernate's caching is split to query caching (just the ids returned), entity cache (the data of the entities) and timestamp cache (which prevent stale data). All in all, they provide a very seemless experience, and make it incredibly easy to significantly improve the performance of the application without having to go and touch all the places where you call the DB.
In addition to that, NHibernate cache is pluggable, moving from the ASP.Net cache (including support for all the usual dependencies tracking) to distributed caching suitable for web farms scenarios.
This also enable other interesting scenarios, I know of at least one place that uses the cache as a fallback in case the database is down, for example.
- Support for distributed scenarios - sharding, distributed caching, cache supported queries are few of the features that relates to that, just of the top of my head.
Googlinglive.coming your entities - Lucene integration - super fast search across your entities, including interesting options such as polymorphic searchs across the graph and safe query language that user are familar with (and no, full text searching at the DB level doesn't come close).
- Flexible - I can extend just about every part of NHibernate that I want. Without changing NHibernate's code, that is, just by using the provided extension mechanism. From supporting wierd database types to adding AOP support to my entities. This means that I don't find the hood welded shut, which is all too often the case, when I need to do something slightly advance.
- Testable - NHibernate itself is easy testable, although I would still recommend going one layer above that for real testing, since it is generally too lower granularity to be useful in most cases.
- Non invasive - if I want to use NHibernate, I don't have to make any signifcant modifications to my code, my entities are POCO classes, without referencing NHibernate or being dependant on it. This is imprtant, because it means that NHibernate accepts the responsability to match my model, not the other way around.
- Complete abstraction - I have written full fledged enterprise applications, with high level f complexity, that had 0 (ZERO) SQL statements in them. I mean that as no queries in the code, no stored procedures, no DDL, nothing. NHibernate took over the entire thing, I didn't have to manage that at all. (Doesn't mean that I didn't test that, or that I wasn't profiling the application to see if it needed indexing or the like, but it was zero cost DB for most of the project).
- High performance options - see above for some of them, in general, NHibernate provides with a lot of options to increase performance. Here is a tidbit that I didn't mention so far, the various fetching straties that you can use (join, subselect, batched select, caching, multi queries, etc).
- Multi database support - you aren't limited to SQL Server, you can work on just about any database that you want. Even if you use SQL Server, the ability to run on a different database is very important, I routinely use this ability to enable me to run unit test on in memory databases, which are blazing fast. Without this, I would have to run tests against a database server, and the cost of the tests would be three orders of magnitude higher.
- Per query (and association) load options - this turn out to be useful in many cases, when I may need this flexiblity in the same unit of work.
- Enable non invasive cross cutting concerns handling. For example, if I want to handle INotifyPropertyChanged in my model, I don't have to add that to my model (thereby tainting it with what is for all intents and purposes UI concerns), I can add this capability directly through NHibernate:
Partial domain models - The ability to merge two diparate domain models into a single one dynamically is pretty powerful when you want to take a base model and use it from another one. This allows the ability to extend the model in some nice ways, such as building a separate library that handles a concerns without having to tie it to a particular domain implementation, or reusing a domain in different context.