Chapter 12. Criteria Queries

NHibernate now features an intuitive, extensible criteria query API. For now, this API is less powerful than the more mature HQL query facilities. In particular, criteria queries do not support projection or aggregation.

12.1. Creating an ICriteria instance

The interface NHibernate.ICriteria represents a query against a particular persistent class. The ISession is a factory for ICriteria instances.

ICriteria crit = sess.CreateCriteria(typeof(Cat));
crit.SetMaxResults(50);
List cats = crit.List();

12.2. Narrowing the result set

An individual query criterion is an instance of the interface NHibernate.Expression.ICriterion. The class NHibernate.Expression.Expression defines factory methods for obtaining certain built-in ICriterion types.

IList cats = sess.CreateCriteria(typeof(Cat))
    .Add( Expression.Like("Name", "Fritz%") )
    .Add( Expression.Between("Weight", minWeight, maxWeight) )
    .List();

Expressions may be grouped logically.

IList cats = sess.CreateCriteria(typeof(Cat))
    .Add( Expression.Like("Name", "Fritz%") )
    .Add( Expression.Or(
        Expression.Eq( "Age", 0 ),
        Expression.IsNull("Age")
    ) )
    .List();
IList cats = sess.CreateCriteria(typeof(Cat))
    .Add( Expression.In( "Name", new String[] { "Fritz", "Izi", "Pk" } ) )
    .Add( Expression.Disjunction()
        .Add( Expression.IsNull("Age") )
    	.Add( Expression.Eq("Age", 0 ) )
    	.Add( Expression.Eq("Age", 1 ) )
    	.Add( Expression.Eq("Age", 2 ) )
    ) )
    .List();

There are quite a range of built-in criterion types (Expression subclasses), but one that is especially useful lets you specify SQL directly.

        // Create a string parameter for the SqlString below
        Parameter paramName = new Parameter("someName", new StringSqlType());

        IList cats = sess.CreateCriteria(typeof(Cat))
            .Add( Expression.Sql(
                new SqlString( new object[] {
                    "lower({alias}.Name) like lower(",
                    paramName,
                    ")" } ),
                "Fritz%",
                NHibernateUtil.String )
            .List();

The {alias} placeholder with be replaced by the row alias of the queried entity.

12.3. Ordering the results

You may order the results using NHibernate.Expression.Order.

IList cats = sess.CreateCriteria(typeof(Cat))
    .Add( Expression.Like("Name", "F%")
    .AddOrder( Order.Asc("Name") )
    .AddOrder( Order.Desc("Age") )
    .SetMaxResults(50)
    .List();

12.4. Associations

You may easily specify constraints upon related entities by navigating associations using CreateCriteria().

IList cats = sess.CreateCriteria(typeof(Cat))
    .Add( Expression.Like("Name", "F%")
    .CreateCriteria("Kittens")
        .Add( Expression.Like("Name", "F%") )
    .List();

note that the second CreateCriteria() returns a new instance of ICriteria, which refers to the elements of the Kittens collection.

The following, alternate form is useful in certain circumstances.

IList cats = sess.CreateCriteria(typeof(Cat))
    .CreateAlias("Kittens", "kt")
    .CreateAlias("Mate", "mt")
    .Add( Expression.EqProperty("kt.Name", "mt.Name") )
    .List();

(CreateAlias() does not create a new instance of ICriteria.)

Note that the kittens collections held by the Cat instances returned by the previous two queries are not pre-filtered by the criteria! If you wish to retrieve just the kittens that match the criteria, you must use SetResultTransformer(CriteriaUtil.AliasToEntityMap).

IList cats = sess.CreateCriteria(typeof(Cat))
    .CreateCriteria("Kittens", "kt")
        .Add( Expression.Eq("Name", "F%") )
    .SetResultTransformer(CriteriaUtil.AliasToEntityMap)
    .List();
foreach ( IDictionary map in cats )
{
    Cat cat = (Cat) map[CriteriaUtil.RootAlias];
    Cat kitten = (Cat) map["kt"];
}

12.5. Dynamic association fetching

You may specify association fetching semantics at runtime using SetFetchMode().

IList cats = sess.CreateCriteria(typeof(Cat))
    .Add( Expression.Like("Name", "Fritz%") )
    .SetFetchMode("Mate", FetchMode.Eager)
    .SetFetchMode("Kittens", FetchMode.Eager)
    .List();

This query will fetch both Mate and Kittens by outer join.

12.6. Example queries

The class NHibernate.Expression.Example allows you to construct a query criterion from a given instance.

Cat cat = new Cat();
cat.Sex = 'F';
cat.Color = Color.Black;
List results = session.CreateCriteria(typeof(Cat))
    .Add( Example.Create(cat) )
    .List();

Version properties, identifiers and associations are ignored. By default, null valued properties and properties which return an empty string from the call to ToString() are excluded.

You can adjust how the Example is applied.

Example example = Example.Create(cat)
    .ExcludeZeroes()           //exclude null or zero valued properties
    .ExcludeProperty("Color")  //exclude the property named "color"
    .IgnoreCase()              //perform case insensitive string comparisons
    .EnableLike();             //use like for string comparisons
IList results = session.CreateCriteria(typeof(Cat))
    .Add(example)
    .List();

You can even use examples to place criteria upon associated objects.

IList results = session.CreateCriteria(typeof(Cat))
    .Add( Example.Create(cat) )
    .CreateCriteria("Mate")
        .Add( Example.Create( cat.Mate ) )
    .List();