Критерии NHibernate выбирают элементы по группам и сумме itemid в другой таблице - PullRequest
4 голосов
/ 20 июля 2010
public class SearchText
{
    public virtual int Id { get; set; }
    public virtual string Text { get; set; }
}

public class SearchTextLog
{
    public virtual int Id { get; set; }
    public virtual SearchText SearchText { get; set; }
    public virtual User User { get; set; }
    public virtual int SearchCount { get; set; }
    public virtual DateTime LastSearchDate { get; set; }
}

Я пытаюсь выбрать первые 5 элементов SearchText на основе суммы их количества в SearchTextLog.В настоящее время мне удалось решить эту проблему, сначала выполнив запрос, чтобы получить первые 5 элементов, а затем используя результат во втором запросе.Мне было интересно, если бы кто-то мог показать мне свет и научить меня, как я могу объединить эти два отдельных запроса в единый блок.

Вот что у меня сейчас:

var topSearchCriteria = Session.CreateCriteria(typeof (SearchTextLog))
            .SetProjection(Projections.ProjectionList()
                            .Add(Projections.GroupProperty("SearchText.Id"))
                            .Add(Projections.Alias(Projections.Sum("SearchCount"), "SearchCount")))
            .AddOrder(Order.Desc("SearchCount"))
            .SetMaxResults(topSearchLimit)
            .List<int>();

return Session.CreateCriteria<SearchText>()
            .Add(Restrictions.In("Id", topSearchCriteria.ToArray()))
            .List<SearchText>();

Изменить:

О нет, я только что понял, что мое текущее решение потеряет важный порядок результатов.Так что мне определенно придется включить запросы.: - /

Редактировать:

Я также попытался использовать двунаправленное сопоставление, чтобы разрешить следующее утверждение, однако не могу заставить его вернуть элементы SearchText.Он просто жалуется, что свойства SearchText не входят в группу.

return Session.CreateCriteria<SearchText>()
                .CreateAlias("SearchTextLogs", "stl")
                .AddOrder(Order.Desc(Projections.Sum("stl.SearchCount")))
                .SetMaxResults(topSearchLimit)        
                .SetResultTransformer(Transformers.AliasToEntityMap)
                .List<SearchText>();

Извините, я не знаю, но Nhibernate совершенно новый для меня и требует совершенно другого мышления.

Ответы [ 2 ]

14 голосов
/ 21 июля 2010

Хорошо, я думаю, что нашел решение.

Мое оригинальное решение по моему вопросу не будет работать, потому что NHibernate пока не поддерживает возможность создавать группу по свойству без добавления его впредложение select (см .: текст ссылки ).

Обдумывая, однако, я натолкнулся на эти классные вещи, называемые ResultTransformers.Используя преобразователь результатов AliasToBean, Nhibernate автоматически сопоставит псевдонимы, которые я даю каждому элементу проекции, свойствам с тем же именем в указанном мной типе.Я просто указал свой объект SearchText (однако мне пришлось добавить дополнительное свойство TotalSearchCount для элемента проекции суммы).Он полностью заполнил мои объекты и вернул их.

return Session.CreateCriteria(typeof(SearchTextLog))
            .CreateAlias("SearchText", "st")
            .SetProjection(Projections.ProjectionList()
                                .Add(Projections.Alias(Projections.GroupProperty("st.Id"), "Id"))
                                .Add(Projections.Alias(Projections.GroupProperty("st.Text"), "Text"))
                                .Add(Projections.Alias(Projections.Sum("SearchCount"), "TotalSearchCount")))
            .SetMaxResults(topSearchLimit)
            .AddOrder(Order.Desc("TotalSearchCount"))
            .SetResultTransformer(Transformers.AliasToBean(typeof(SearchText)))
            .List<SearchText>();

Я удивлен, что это было не так просто сделать.У меня ушло от 4 до 5 часов исследований и разработки, чтобы понять это.Надеюсь, мой опыт работы в NHibernate станет легче с ростом опыта.

Надеюсь, это поможет кому-то еще!

1 голос
/ 20 июля 2010

это не работает?

var critterRes = Session.CreateCriteria(typeof (SearchTextLog))
            .SetProjection(Projections.ProjectionList()
                            .Add(Projections.GroupProperty("SearchText"))
                            .Add(Projections.Property("SearchText"))
                            .Add(Projections.Alias(Projections.Sum("SearchCount"), "SearchCount")))
            .AddOrder(Order.Desc("SearchCount"))
            .SetMaxResults(topSearchLimit)
            .List<SearchText>()
...