views:

310

answers:

3

I am having trouble getting my query by criteria to work.

I want to filter the UserPublications collection by userId but it is not filtering. The ClientPublications collection has filtered correctly though.

Any advice?

Thanks in advance.

public IList<ClientReport> GetAvailableClientReports(int userId)
    {
        ICriteria criteria = NHibernateSession.CreateCriteria(typeof(ClientReport))
            .CreateCriteria("ClientPublications")                
            .Add(Expression.Eq("IsDownloaded", true))
            .SetResultTransformer(CriteriaUtil.DistinctRootEntity)
            .AddOrder(Order.Asc("Name"))
            .CreateCriteria("UserPublications")                    
            .CreateAlias("ClientUser", "user")
            .Add(Expression.Eq("user.UserId", userId));

        return GetByCriteria(criteria);
    }
A: 

If you mapped the UserId property as "Id" in your mapping file (which you probably do if you used the same conventions as in this question), it should be:

.Add(Expression.Eq("user.Id", userId))

The Id property is a special case in NHibernate

Jan Willem B
If his Id property is called UserId, then he should use 'UserId' ...
Frederik Gheysels
Not necessarily. Both ways are equal. From the documentation: "The special property (lowercase) id may be used to reference the unique identifier of an object. (You may also use its property name.)"I thought only the .Id option was valid, so the answer is useless nonetheless, also considering "id" should be written lowercase.:)
Jan Willem B
this did not make any difference, but thanks anyway.
empo
A: 

why don't you create an alias for UserPublications and add the expression there? like

.CreateCriteria("UserPublications", "up")                    
.Add(Expression.Eq("up.ClientUser.UserId", userId));

or maybe

.CreateCriteria("UserPublications", "up")                    
.CreateAlias("up.ClientUser", "user")
.Add(Expression.Eq("user.UserId", userId));

as far as i can see calling

.CreateAlias("ClientUser", "user")

depends on NH's ability to detect where ClientUser exists and create the join which may not be working (bug or otherwise)

Jaguar
This did not make any difference either, but thanks anyway. What is interesting is that when the query is first executed NHibernate does not even query the UserPublication table. Its not until I start to drill down in the debugger that more queries are executed, however it is getting all the UserPublication rows and NOT restricting by user id. This is happening of course as expected due to lazy loading. Nonetheless I would still expect NHibernate to query the UserPublication table when the criteria query is executed but clearly this is not happening. hmmmmmmmmmmmmm......
empo
A: 

For future ref, I got it working by adding a filter in the mapping file

First define the filter in the parent class mapping:

<filter-def name="userFilter">
  <filter-param name="userId" type="System.Int32"/>
</filter-def>

Then define filter further in the mapping to the collection

<bag name="UserPublications" access="property" lazy="true" cascade="all-delete-orphan">      
  <key column="ClientPublicationID"/>
  <one-to-many class="ReportMgr.Model.ClientUserPublication, ReportMgr.Model" />
  <filter name="userFilter" condition="ClientUserID = :userId"></filter>
</bag>

Then enable the filter and specify the parameter value just before executing the ICriteria query:

NHibernateSession.EnableFilter("userFilter").SetParameter("userId", userId);
ICriteria criteria = NHibernateSession.CreateCriteria(typeof(ClientReport))
            .CreateCriteria("ClientPublications")
            blah blah blah                   
return GetByCriteria(criteria);
empo
this solution was obtained thanks to this posthttp://ayende.com/Blog/archive/2009/05/04/nhibernate-filters.aspx
empo