NHibernate Detached Criteria is not Reusable
While working on a paging feature for our application I discovered that the NHibernate detached criteria is not reusable. My goal was to create a single call to a repository using one detached criteria. The Idea was to reuse the detached criteria to perform two queries. One query to retrieve the total number records. The second query to retrieve a list of items for the specified page number and number of records per a page.
On the repository we have the following method.
QueryResult<T> FindBy(DetachedCriteria query,int pageNumber,int numberOfItemsToDisplay);
The QueryResult returned from the repository has a total and the items for the requested page.
Here is my implementation of FindBy. I had a few helper methods but removed them to fully illustrate the problem.
The confusing part
public class QueryResult<T>
{
public int TotalNumberOfItems { get; private set; }
public IEnumerable<T> Items { get; private set; }
public QueryResult(int totalNumberOfItems, IEnumerable<T> items)
{
TotalNumberOfItems = totalNumberOfItems;
Items = items;
}
}
Here is my implementation of FindBy. I had a few helper methods but removed them to fully illustrate the problem.
public QueryResult<T> FindBy(DetachedCriteria query, int pageNumber, int numberOfItemsToDisplay)
{
var pageIndex = pageNumber - 1;
var firstResult = 0;
if (pageIndex != 0)
firstResult = pageIndex * numberOfItemsToDisplay;
ICriteria executableQuery = query.GetExecutableCriteria(CurrentSession());
executableQuery.SetProjection(Projections.RowCount());
var count = executableQuery.UniqueResult<int>();
query.SetProjection(null);
query.SetResultTransformer(CriteriaSpecification.RootEntity);
var items = FindBy(query.SetFirstResult(firstResult).SetMaxResults(numberOfItemsToDisplay));
return new QueryResult<T>(count,items);
}
The confusing part
ICriteria executableQuery = query.GetExecutableCriteria(CurrentSession());
executableQuery.SetProjection(Projections.RowCount());
var count = executableQuery.UniqueResult<int>();
//Reset
query.SetProjection(null);
query.SetResultTransformer(CriteriaSpecification.RootEntity);
//Excute new query
var items = FindBy(query.SetFirstResult(firstResult).SetMaxResults(numberOfItemsToDisplay));
In Summary
I find the behaviour of the detached criteria object to be somewhat odd. It might just be a misunderstanding on my part but the API led me to believe that the ICriteria object had no relationship to the detached query. The coupling between the ICriteria object and detached criteria was a big surprise. If I were to ask I bet the NHibernrate/Hibernate team or even Oren Eini could provide me with an explanation.
0 comments:
Post a Comment