Thursday, December 1, 2011

Programmatic way to add filters for NHibernate mappings

NHibernate filters is a powerful mechanism for selective filtering of records. Read more here or here.

This post is to document the way to add filters programmatically rather than declaratively (in binding files).

Let’s start with a declarative configuration.

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" 
    namespace="yournamespace" assembly="yourassembly">
    <class name="Parent" table="[dbo].[Parents]" >
        <id name="Oid" column="[OID]" type="Int32" >
            <generator class="native" />
        </id>
        <property name="Name" column="Name" type="String" not-null="false" length="50" /> 
        <bag name="Children" inverse="true" cascade="all-delete-orphan" lazy="true" >
            <key>
                <column name="[ID_PARENT]" />
            </key>
            <one-to-many class="Child" />
            <filter name="association-level-filter" condition="condition" />
        </bag>
        <filter name="entity-level-filter" condition="condition" />
    </class>
</hibernate-mapping>
 

Note that the mapping defined the entity of type Parent with a reference to a list of entities of type Child. Each Child points to its Parent.

Note also that there are actually two filters – the entity-level filter applies to queries to type Parent and the association-level filter applies to queries involving the list of dependant entities.

The entity-level filter is available on the mapping object easily:

foreach ( var mapping in config.ClassMappings )
{
    mapping.AddFilter( "name", "criteria" );
}

However, to get the association-level filter you have to dig deeper to get the properties of type Bag from the actual mapping:

foreach ( var mapping in config.ClassMappings )
{
    mapping.AddFilter( "name", "condition" );
    foreach ( var property in mapping.PropertyIterator )
        if ( property.Value is Bag )
        {
            Bag bagProperty = (Bag)property.Value;
 
            bagProperty.AddFilter( "name", "condition" );
        }
}