Originally announced on my own blog here: Using Lambda Expressions with NHibernate
I love NHibernate, but I've never been a fan of the 'magic strings' used in the ICriteria API. Now we have .Net 3.5, and the ability to have strongly-typed queries built into the language, and a corresponding NH-Contrib project (NHibernate.Linq) to allow us to use LINQ with NHibernate.
However, there are still times when you need to use the ICriteria API (or HQL) to achieve the results you want.
Consider the following query:
session.CreateCriteria(typeof(Person), "personAlias")
.SetFetchMode("personAlias.PersonDetail", FetchMode.Eager)
// to prevent select n+1
.SetLockMode("personAlias", LockMode.Upgrade)
// to read-lock the data until commit
.Add(Expression.Like("Name", "%anna%"))
// includes the name 'Polyanna', 'Annabella', ...
...
LINQ provides a high-level abstraction of a query that can potentially be run against any datasource. However, this abstraction comes at a cost (try writing the above query in LINQ). LINQ (out of the box) has no concept of:
So ICriteria and HQL will not be obsolete - they will quite happily live side-by-side with LINQ.
In order to implement LINQ, .Net 3.5 also introduced both Extension Methods and Lambda Expressions
Extension methods allow us to extend the ICriteria interface with our own methods, while Lambda Expressions allow us to create typesafe expressions that can be examined at runtime. So with some extra syntactic sugar, the above query can be written as:
session.CreateCriteria(typeof(Person), () => personAlias)
.SetFetchMode(() => personAlias.PersonDetail, FetchMode.Eager)
.SetLockMode(() => personAlias, LockMode.Upgrade)
.Add(SqlExpression.Like<Person>(p => p.Name, "%anna%"))
...
The 'magic strings' are gone! This code uses a combination of Extension Methods and Lambda Expressions to create a typesafe version of the ICriteria. We can now also use our refactoring tools to rename, or find references to properties safe if the knowledge that the IDE will pick them up.
The extensions methods required to do this have been packaged up into a project (link below), making it easy to add this to your own .Net 3.5 NHibernate project.
With the addition of projects like Fluent NHibernate , perhaps 'magic strings' will finally become a thing of the past.