From the time I posted this question, I've managed to find a workaround / solution which others might find useful as well.
Basically, in such case you must first create another query which distinctly selects the primary keys of the main query, together with pagination. Since the DISTINCT(ID) will return only the results you want, you can use the pagination of SQL without any problems. Then, you re-run the main query, without pagination but using a condition where the ID is in one of the list returned. I created a general method which takes a criteria, looks up the IDs returned and adds them as a condition to the main criteria. Code below:
public static void LimitCriteriaByPrimaryKeys(this NHibernate.ICriteria criteria, string primaryKeyName, int pageNum, int pageSize)
{
var session = NHManager.Instance.GetCurrentSessionFromContext();
if (pageSize <= 0) pageSize = Int32.MaxValue - 1;
var nhSession = NHManager.Instance.GetCurrentSessionFromContext();
var pagingCriteria = (ICriteria)criteria.Clone();
IList ids = null;
var pKeyIDName = Projections.Property(primaryKeyName);
var pKeyProjection = Projections.Distinct(pKeyIDName);
{
{
//paging
pagingCriteria.SetProjection(pKeyProjection); //sets the primary key distinct projection
if (pageSize > 0)
{
if (pageNum < 1)
pageNum = 1;
int skipAmt = (pageNum - 1) * pageSize;
pagingCriteria.SetFirstResult(skipAmt);
pagingCriteria.SetMaxResults(pageSize);
ids = pagingCriteria.List(); //this returns the distinct list of IDs which should be returned for the given page & size
}
}
}
{
if (ids != null && ids.Count > 0)
{
criteria.Add(Expression.In(pKeyIDName, ids)); //adds the primary key restriction
var crit = criteria;
crit.SetResultTransformer(new NHibernate.Transform.DistinctRootEntityResultTransformer());
}
else
{
criteria.Add(Expression.Eq(pKeyIDName, 0)); //this is added specifically so that the main criteria returns NO results
criteria.Add(Expression.Eq(pKeyIDName, 1));
}
}
}
The methods NHManager.Instance.GetCurrentSessionFromContext();
can be replaced with your own method to retrieve the current session from the session factory.
Hope it helps!