-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 12 posts ] 
Author Message
 Post subject: Get Count without loading collection
PostPosted: Wed Nov 23, 2005 4:03 pm 
Beginner
Beginner

Joined: Mon Sep 26, 2005 5:57 pm
Posts: 39
How can I get count of a collection (as a result of a query) instead of loading the collection and then getting the count?

I would prefer to use ICriteria if possible instead of HQL.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 23, 2005 6:28 pm 
Expert
Expert

Joined: Fri Oct 28, 2005 5:38 pm
Posts: 390
Location: Cedarburg, WI
I've done something similar, based on a tip in the Hibernate documentation:

Code:
string queryText = "...";
QueryParameters queryParameters = ...;

Enumerator enumerator = session.Enumerable(
    queryText, queryParameters).GetEnumerator();

int count = 0;
if (enumerator.MoveNext())
{
    count = Convert.ToInt32(enumerator.Current);
}


Apparently you have to use HQL, I don't see any overloads supporting ICriteria ...


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 28, 2005 1:47 pm 
Senior
Senior

Joined: Sat Sep 10, 2005 3:46 pm
Posts: 178
I dont think you can do it with ICriteria but there is a simple way with HQL.

Code:
//create a filter on the collection
IQuery listQuery = this.Session.CreateFilter(documents, "Select count(*)");

//return the count
return (int)listQuery.UniqueResult();


I like to check if the collection has already been loaded yet though. That way, if the collection is already loaded, I dont have to hit the database.

Code:
   if(documents is PersistentCollection){      
            //get the list as a proxy
            PersistentCollection listProxy = documents as PersistentCollection;

            //if the list hasnt been initialized, query the collection to determine the count
            //this will be faster than bringing the whole collection down
            if(listProxy.IsDirectlyAccessible == false){
               //create a count filter for the collection
               IQuery listQuery = this.Session.CreateFilter(documents, "Select count(*)");

               //return the count
               return (int)listQuery.UniqueResult();
            }

//if we made it this far then use the regular ilist count operation
return documents.Count;
         }


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 29, 2005 10:13 am 
Contributor
Contributor

Joined: Thu May 12, 2005 9:45 am
Posts: 593
Location: nhibernate.org
Note that you should use:
Code:
if( NHibernate.NHibernateUtil.IsInitialized(documents) )
    ...

_________________
Pierre Henri Kuaté.
Get NHibernate in Action Now!


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 29, 2005 2:41 pm 
Newbie

Joined: Thu Sep 29, 2005 3:30 pm
Posts: 3
This may not be what you are looking for, but this is how I did.

return (int) Session.Find(queryString)[0];


Top
 Profile  
 
 Post subject:
PostPosted: Tue Nov 29, 2005 7:53 pm 
Senior
Senior

Joined: Sat Sep 10, 2005 3:46 pm
Posts: 178
thanks for the tip KPixel. With Kpixel's tip my code above changed to

Code:
if(documents is PersistentCollection){      

            //if the list hasnt been initialized, query the collection to determine the count
            //this will be faster than bringing the whole collection down
            if(NHibernate.NHibernateUtil.IsInitialized(documents) == false){
               //filter the list for the specified document
               IQuery listQuery = this.Session.CreateFilter(documents, "Select count(*)");

               //return the count
               return (int)listQuery.UniqueResult();
            }
         }
         
         //if we made it this far then use the regular ilist count operation
         return documents.Count;


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 30, 2005 8:52 am 
Contributor
Contributor

Joined: Thu May 12, 2005 9:45 am
Posts: 593
Location: nhibernate.org
I assume you forgot to remove the line:
Code:
if(documents is PersistentCollection){

:wink:

_________________
Pierre Henri Kuaté.
Get NHibernate in Action Now!


Top
 Profile  
 
 Post subject: Lazy Load: Count before loading
PostPosted: Mon Jan 16, 2006 7:31 pm 
Newbie

Joined: Mon Jan 16, 2006 7:27 pm
Posts: 1
jnapier wrote:
I dont think you can do it with ICriteria but there is a simple way with HQL.

Code:
//create a filter on the collection
IQuery listQuery = this.Session.CreateFilter(documents, "Select count(*)");

//return the count
return (int)listQuery.UniqueResult();


I like to check if the collection has already been loaded yet though. That way, if the collection is already loaded, I dont have to hit the database.

Code:
   if(documents is PersistentCollection){      
            //get the list as a proxy
            PersistentCollection listProxy = documents as PersistentCollection;

            //if the list hasnt been initialized, query the collection to determine the count
            //this will be faster than bringing the whole collection down
            if(listProxy.IsDirectlyAccessible == false){
               //create a count filter for the collection
               IQuery listQuery = this.Session.CreateFilter(documents, "Select count(*)");

               //return the count
               return (int)listQuery.UniqueResult();
            }

//if we made it this far then use the regular ilist count operation
return documents.Count;
         }


In regards to the code above, the first param of session.Filter is a collection. What I can't figure out is which collection I should be passing to that?

I basically have an application that searches for data and then displays it. However, if based on the search criteria, more than 50 items are going to be returned, the user has to narrow their search. The problem is that if the user enters criteria that matches 250,000 NHibernate loads all of them in order for me to get a count.

Thanks


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 17, 2006 5:30 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
session.Filter works only on persistent collections. If you are searching for data, you probably have a simple ArrayList, you can't call Filter on that.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 27, 2006 2:18 am 
Beginner
Beginner

Joined: Wed Jun 08, 2005 4:59 pm
Posts: 27
A follow-up question: I am trying to construct a query that does something equivalent to a sql "top" clause on the count of subcollection. The HQL is:

Code:
from ParentEntity parent order by count(parent.Children) desc

which I follow with:

Code:
IQuery query = session.CreateQuery(queryString);
query.SetFirstResult(0);
query.SetMaxResults(10);


The problem is that it tries to bring in ALL children and ALL children's children and so forth. Is there a way to do this more efficiently and have it generate SQL that effectively does an order by count()?

Thanks!


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jan 27, 2006 5:13 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
Make sure your children collection is set to be lazy and that outer-join is disabled for it.


Top
 Profile  
 
 Post subject:
PostPosted: Sat Jan 28, 2006 1:35 am 
Beginner
Beginner

Joined: Wed Jun 08, 2005 4:59 pm
Posts: 27
Yup, figured that out, thanks!!!

-MT


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 12 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.