Mike Nichols - Son of Nun Technology

Querying Components with NHibernate Criteria

Working with NHibernate's query criteria API is logical, but sometimes I slip. For example, say I have a class Timesheet and the timesheet has property (which is also mapped) named Employee and a component named PayrollPeriod:

public class Timesheet : DomainObject<int>, ITimesheet

{

 

 

    private IEmployee _employee;

    public virtual IEmployee Employee

    {

        get

        {

            return _employee;

        }

    }

 

 

    private IRange<DateTime> _payrollPeriod = new Range<DateTime>(DateTime.MinValue, DateTime.MaxValue);

    public virtual IRange<DateTime> PayrollPeriod

    {

        get

        {

            return _payrollPeriod;

        }

    }

 

 

}


Now, when i query for a timesheet i want to get a timesheet with an Employee.Id = 36.
I might think the Criteria would look like this:


ICriteria crit = session.CreateCriteria(typeof(Timesheet);
crit.Add(Expression.Eq("Employee.Id",36));


Now, that would be fun but it would be wrong. Since Employee is a mapped class, it is really and association. So I neeed to do the following:
ICriteria crit = session.CreateCriteria(typeof(Timesheet);
crit.CreateCriteria("Employee").Add(Expression.Eq("Id",36));


This creates a SubCriteria object via what is called an 'association path' which is really just the property name. This tells NHibby to nest a criteria inside the main Timesheet criteria (inner join).


Now, let's say I have a component inside Timesheet called PayrollPeriod. This PayrollPeriod class might have two properties: Start and End:

    public interface IRange<T>: IValueObject  where T :  IComparable<T>

    {

        T Start { get;}

        T End { get;}

        bool Contains(T valueToFind);

    }

When I want to query on the Timesheet for a PayrollPeriod which matched certain criteria, I will employ the period notation 'Component.PropertyName' to get there. So it would look like this:

ICriteria crit = session.CreateCriteria(typeof(Timesheet);
crit.Add(Expression.Eq("PayrollPeriod.Start",new DateTime(2006,9,9)));

If I were to try to do an association type mapping like we did with Employee, we'd find NHibby complaining because it thinks we are trying to tell it that 'Start' is a property of 'Timesheet'.