
November 30, 2011 13:31 by
Simon
When reading data from the database with NHibernate, there are now more options than ever. It is my opinion that some of these options are better than others and that they should be used in the following order of preference.
-
Wherever possible the methods available to us on the session object should be used ahead of anything else.
Session.Get<Cat>(1);
-
If we need to do anything more complex than reading by Id or getting all records from a table then we have to construct a where clause somehow. NHibernate 3 has brought with it Linq to NHibernate which allows you to construct queries such as:
var cat = (from c in Session.Query<Cat>()
where c.Name == "Fluffy"
select c).SingleOrDefault();
-
There are a number of scenarios that are not well suited to Linq to NHibernate. Consider a search screen where the user enters search criteria which results in clauses only being added to the 'where' part of the query where the user has selected a value - in other words it is built up at runtime. In this case you must use the query over api.
var cat =
Session.QueryOver<Cat>()
.Where(c => c.Name == "Fluffy")
.SingleOrDefault();
-
The query over API is built on top of the criteria API. I don't know for sure, but there may well be some functionality not supported by the query over API in which case you may be forced to use the criteria API instead - I have never come across a scenario however.
var cat = Session.CreateCriteria<Cat>()
.Add(Restrictions.Eq("Name", "Fluffy"))
.UniqueResult<Cat>();
The magic strings here play havoc with refactoring however, which is why the crieria API is so far down my list.
-
Some complex queries aren't possible to construct with the criteria or query over API's in which case your only choice is to use HQL (unless you want to use an SP or native SQL instead). In my experience these scenarios are few and far between. HQL is one big magic string and therefore suffers from the same refactoring problems as the criteria API. If you use it, you must have a strong suite of unit (or maybe more accurately, integration) tests backing it. I would suggest however, that if you really can't construct your query using anything other than HQL you probably have a design issue and maybe an ORM such as NHibernate or even a relational database isn't the right choice in this circumstance.
var cat = Session.CreateQuery("from Cat c where c.Name = :name")
.SetString("name", "Fluffy")
.UniqueResult<Cat>();
241f87cc-0422-47c4-85d1-476cdb56d96d|0|.0