NHibernate Lambda Extensions - нетерпеливая загрузка ассоциаций коллекции

У меня есть критерий запроса для сайта социальной сети. Объект Person имеет коллекцию друзей (также объектов-лиц). Запрос захватывает первых N друзей, но я также хочу загрузить связанный объект MainProfileImage, а затем последующий связанный объект MediumThumbnail.

Я легко могу сделать это в HQL:

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

Вот усилие My Criteria. Почему-то это ничего не возвращает!

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>();
}

person reach4thelasers    schedule 11.11.2009    source источник
comment
Почему бы вам тогда просто не оставить HQL на месте?   -  person John Rayner    schedule 12.11.2009


Ответы (1)


Я считаю, что порядок ваших операторов заставляет запрос генерировать нежелательный SQL, который вы получаете (следовательно, нет результатов). Вот как должно быть:

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>();
}

Кроме того, из вашего описания неясно, из какой ассоциации вы хотите получить данные MainProfileImage и MediumThumbnail. Поскольку вы используете его в своем операторе Criteria, вы запрашиваете данные, поступающие от основного объекта Person, друзей которого вы получаете, когда используете friendsAlias. Я изменил его, чтобы использовать вместо него personAlias, поскольку я считаю, что именно здесь вы хотите связать данные.

person tolism7    schedule 12.11.2009
comment
Это сработало отлично, спасибо! Мне действительно пришлось сменить friendAlias ​​на personAlias ​​- это то, что я не могу понять, но это сработало! Обновите свой ответ, чтобы отразить это. Еще раз спасибо! - person reach4thelasers; 12.11.2009
comment
Ответ обновлен! Чтобы избежать путаницы с псевдонимами, попробуйте сформулировать запрос словесно. В запросе Criteria мы говорим, что получите все объекты person, которые являются друзьями данного объекта person, чей идентификатор у меня есть, что означает, что вы начинаете свой запрос с элементов в коллекции друзей данного объекта person. Вот почему personAlias ​​относится к вашим результатам (друзьям данного объекта oerson), а friendsAlias ​​относится к данному объекту person. Путаница также возникает из-за неудачного названия псевдонимов. - person tolism7; 12.11.2009