views:

257

answers:

3

I have to display some objects which are stored in a relational database and I use fluent NHibernate to get them.

Since I need paging, I have to get both - the count of all objects, and the objects for the current page themselves.

The ICriteria for both purposes is very similar up to a point - for count i finally add .SetProjection(Projections.RowCount()) and for current object list I add SetFirstResult, AddOrder and SetMaxResults

Is there any way I could undo the projection on the criteria and reuse criteria for the results themselves, or do I have to reconstruct the criteria for that purpose?

hibernate forums suggests a way that does not work.

A: 

This post is almost identical to what you're asking for.

http://stackoverflow.com/questions/1751422/removing-order-from-nhibernate-criteria-query

-Doug

Doug
+1  A: 

I would write a method encapsulating the query logic including restrictions, grouping, ...:

public DetachedCriteria GetCriteria()
{
    return DetachedCriteria.For<Entity>()
        .Add(Restrictions.Eq(...))
        .Add(...);
}

And then send requests to the database:

var count = GetCriteria()
    .GetExecutableCriteria(session)
    .SetProjection(Projections.Count(Projections.Id()))
    .UniqueResult<int>();

var result = GetCriteria()
    .GetExecutableCriteria(session)
    .SetFirstResult(0) 
    .SetMaxResults(10)
    .List<Entity>();

To further optimize this you could take a look at this excellent blog post in which Ayende Rahien talks about NHibernate Futures.

Darin Dimitrov
A: 
public static DetachedCriteria Clone(this DetachedCriteria criteria)
{
   var dummy = criteria.ToByteArray();
   return dummy.FromByteArray<DetachedCriteria>();
}
var criteria = GetCriteria()
var count = criteria 
    .Clone()
    .GetExecutableCriteria(session)
    .SetProjection(Projections.Count(Projections.Id()))
    .UniqueResult<int>();

var result = criteria 
    .GetExecutableCriteria(session)
    .SetFirstResult(0) 
    .SetMaxResults(10)
    .List<Entity>();
bobac