When I posted about NHibernate Projections I used HQL (IQuery) in the repository to define the query.
There are a some things that I don’t like about HQL. For example the query is defined as a string. Strings are problematic because errors can’t be detected at compile time. ICriteria queries go some way to alleviating this although they are certainly not perfect in this regard. You are writing tests against your repositories though aren’t you?
But the reliance on strings is not the only problem with HQL. Today I needed to create a search screen. I wanted to use a variation of the technique that Ayende demonstrates here. With HQL the repository methods become ugly very quickly (and I mean wake up sweating at 2 am ugly). There is a mass of conditional string concatenation. And for each parameter I need to change 2 pieces of code (the code that builds the HQL and the code that binds the parameters).
So I decided to figure out how to use ICriteria to return a DTO. It transpires that the following code produces the same result as the HQL that I used before:
public List<InspectorDropDownDTO> GetAll()
{
ICriteria q = session.CreateCriteria(typeof(Inspector), "i");
q.CreateAlias("Person", "p");
q.SetProjection(Projections.ProjectionList()
.Add(Projections.Property("i.ID"), "InspectorID")
.Add(Projections.Property("p.FirstName"), "FirstName")
.Add(Projections.Property("p.LastName"), "LastName"));
q.SetResultTransformer(Transformers.AliasToBean(typeof(InspectorDropDownDTO)));
return q.List<InspectorDropDownDTO>();
}
It should be noted that the DTO itself is different with this method. A default constructor is now all that’s needed because the AliasToBean transformer seems to work properly with ICriteria.
public class InspectorDropDownDTO
{
private long _inspectorID;
private string _firstName;
private string _lastName;
public long InspectorID { get { return _inspectorID; } set { _inspectorID = value; } }
public string FirstName { get { return _firstName; } set { _firstName = value; } }
public string LastName { get { return _lastName; } set { _lastName = value; } }
public string FullName { get { return FirstName + " " + LastName; } }
}
Also note that you no longer need to import the DTO in an hbm.xml file.
You really need to pop on over to .Net 3.0.
This gets MUCH shorter.
public class InspectorDropDownDTO{ private long _inspectorID; private string _firstName; private string _lastName; public long InspectorID { get { return _inspectorID; } set { _inspectorID = value; } } public string FirstName { get { return _firstName; } set { _firstName = value; } } public string LastName { get { return _lastName; } set { _lastName = value; } } public string FullName { get { return FirstName ” “ LastName; } }}
Agreed. I am very happy that VS 2008 it’s going to RTM this month. I have used it on some other projects but it was not an option for my current one because of its beta status. That will all change in a few weeks…