Parameter lists in NHibernate


Occasionally I need to return a set of entites that match a collection of parameters.  In SQL, I would use the “IN” clause, then manually create each parameter in ADO.NET.  With NHibernate, that’s not necessary anymore.  NHibernate has built-in capabilities for a collection parameter, creating all the necessary ADO.NET parameters behind the scenes.

For example, suppose my database has the following structure (from Northwind):

What I’m trying to do is to load up all Products for a certain set of Categories.  My Product and Category class are nothing interesting:

public class Category
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Category Category { get; set; }
}

I didn’t bother mapping all of the properties, just the ones for the classes defined above.  Here are the mapping files:

<class name="Category" table="Categories">
    <id name="Id" column="CategoryID" type="int">
        <generator class="assigned" />
    </id>
    <property name="Name" not-null="true" column="CategoryName" />
</class>

<class name="Product" table="Products">
    <id name="Id" column="ProductId" type="int">
        <generator class="assigned" />
    </id>
    <property name="Name" not-null="true" column="ProductName" />
    <many-to-one name="Category" column="CategoryID">
    </many-to-one>
</class>

When using plain HQL, I need to use the SetParameterList method on the IQuery object:

[Test]
public void Should_get_products_by_categories_correctly_using_HQL()
{
    ISession session = GetSession();
    string hql = @"from Product p
                   where p.Category in (:categories)";

    var categoriesToSearch = new[] {new Category {Id = 1}, new Category {Id = 2}};

    var query = session.CreateQuery(hql);
    query.SetParameterList("categories", categoriesToSearch);

    var products = query.List<Product>();

    products.Count.ShouldEqual(24);
}

When using the Criteria API, I’ll need to use the InExpression:

[Test]
public void Should_get_products_by_categories_correctly_using_criteria()
{
    ISession session = GetSession();
    var criteria = session.CreateCriteria(typeof(Product));

    var categoriesToSearch = new[] {new Category {Id = 1}, new Category {Id = 2}};
    criteria.Add(new InExpression("Category", categoriesToSearch));
    var products = criteria.List<Product>();

    products.Count.ShouldEqual(24);
}

When I execute both of these, NHibernate produces the correct IN expression for each.  Unfortunately, I am ashamed to say I initially tried to create the parameter list myself.  Next time, I’ll know better.

Services in Domain-Driven Design