nhibernatecriteriaicriterianhlambdaextensions

NHibernate Lambda Extensions - Eager Loading a collection's assosciations


I've got a Criteria Query for a social networking site. A Person object has a collection of Friends (also person objects). The query grabs the first N friends, but I also want to eager load an associated object MainProfileImage and then a subsequent associated object MediumThumbnail.

I can do this in HQL easily:

select friends from Person person inner join person.Friends friends inner join fetch friends.MainProfileImage image inner join fetch image.MediumThumbnail where person = :person1 order by friends.LatestLogin desc

Here's My Criteria effort. For some reason this doesn't return anything!

public static IList<Person> GetFriends(Person person, int count)
{
    Person personAlias = null;
    Person friendAlias = null;

    ICriteria criteria = NHibernateSessionManager.Instance.GetSession()
        .CreateCriteria(typeof (Person), () => personAlias)
        .CreateCriteria(() => personAlias.Friends, () => friendAlias, JoinType.LeftOuterJoin)
        .CreateCriteria(() => friendAlias.MainProfileImage, JoinType.InnerJoin)
        .CreateCriteria(() => friendAlias.MainProfileImage.MediumThumbnail, JoinType.InnerJoin)
        .AddOrder(() => personAlias.LatestLogin, Order.Desc)
        .Add<Person>(p => p.ID == person.ID)
        .SetMaxResults(count);
    return criteria.List<Person>();
}

Solution

  • I believe that the order of your statements causes the query to generate the not desired SQL you are getting (hence no results). Here is how it should be:

    public static IList<Person> GetFriends(Person person, int count)
    {
        Person personAlias = null;
        Person friendAlias = null;
    
        ICriteria criteria = NHibernateSessionManager.Instance.GetSession()
            .CreateCriteria(typeof (Person), () => personAlias)
            .CreateCriteria(() => personAlias.Friends, () => friendAlias, JoinType.LeftOuterJoin)
            .Add<Person>(p => p.ID == person.ID)
            .CreateCriteria(() => personAlias.MainProfileImage, JoinType.InnerJoin)
            .CreateCriteria(() => personAlias.MainProfileImage.MediumThumbnail, JoinType.InnerJoin)
            .AddOrder(() => personAlias.LatestLogin, Order.Desc)
            .SetMaxResults(count);
        return criteria.List<Person>();
    }
    

    Furthermore by your description it is not clear from which association you want to get the MainProfileImage and MediumThumbnail data from. As you are using it in your Criteria statement you are asking the data to come from the main Person object whose friends you are getting as you are using the friendsAlias. I have changed it to use the personAlias instead as I believe this is where you mean to associate the data from.