Wednesday, November 29, 2006

NHibernate repository variation on the Criteria

After reading Dave Donaldson post on NHibernate repository, I was pleasantly surprised on how similar our implementations are. By 'our' I mean Kevin Spargue and I; we are using NHibernate on one of our projects. This is my third NHibernate project and this time around we have enough time to sit down and make corrections to hard learned lessons of using NHibernate. One of those days I will get around publishing our version of the NHibernate repository, but for right now I would like to add our variation on dealing with criterias.

Originally we started with the similar implementation as in Dave's repository:
public static Collection FindByProperty(string property, object value)
with an overload
public static Collection FindByProperty(string[] property, object[] value)

but then we have decided against it, and end up with creating a class wrapper that have included property value, name and operator. This implementation helped us to reduce the number of methods we need to maintain and have provided us more flexibility when it comes to & finding/filtering data.

Repository methods
public static IList Find(QueryValueCondition[] queryValueConditions, QueryOrCondition[] queryOrConditions)
where T : IPersist
{
if (queryValueConditions == null) queryValueConditions = new QueryValueCondition[0];
if (queryOrConditions == null) queryOrConditions = new QueryOrCondition[0];
IList results = new List();
Type type = typeof(T);
IList list = Find(type, queryValueConditions, queryOrConditions);
foreach (T item in list)
results.Add(item);
return results;
}

public static IList Find(Type type, QueryValueCondition[] queryValueConditions, QueryOrCondition[] queryOrConditions)
{
IList results = Accessor.LoadList(type, queryValueConditions, queryOrConditions);
return results;
}

Accessor implementation (Helper class consists of a few static methods that help us final query assembly.)

public static IList LoadList(Type type, QueryValueCondition[] queryValueConditions, QueryOrCondition[] queryOrCondition)
{
IList results = null;
ICriteria criteria = NHibernateSession.CreateCriteria(type);
foreach (QueryValueCondition valueCondition in queryValueConditions)
criteria.Add(Helper.GetCritria(valueCondition));
foreach (QueryOrCondition orCondition in queryOrCondition)
criteria.Add(Helper.GetOrExpression(orCondition));
results = criteria.List();
return results;
}

I will not dive into the details of the methods, but I do want to talk about: QueryValueCondition and QueryOrCondition.

QueryValueCondition class consists of properties wrapped around fields:
string _propertyName = string.Empty;
object _propertyValue = null;
Operators _operators = Operators.Equals;

Operators is a simple enumeration
public enum Operators
{
Equals,
GreaterThan,
GreaterThanEqualTo,
LessThan,
LessThanEqualTo,
Like,
IsNull,
In,
IsNotNull
}

This class allowed us to group a set of data into a logical unit, that contains everything we need to be able to retrieve data on a passed property value.


QueryOrCondition class contains wrap around properties for following fields:
QueryValueCondition _leftCondition = null;
QueryValueCondition _rightCondition = null;

Just an additional class that allow to group multiple properties into OR condition. So now we can use one Find method to get data by one or more properties and we have a power of matching it by various conditions.

2 comments:

Tien said...

Is there source code available and examples of some sorts

WaYdotNET said...

it's possible the code? thanks