2010-07-20 7 views
3
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 элементов, а затем используя результат во втором запросе. Мне было интересно, может ли кто-нибудь показать мне свет и научить меня, как я могу объединить эти два отдельных запроса в единое целое.NHibernate Criteria выбирает товары по группе по сумме и сумме товаров в другой таблице

Вот что я в настоящее время:

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

Edit:

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

Edit:

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

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

Простите мое невежество, но Nhibernate совершенно новое для меня, и требует совершенно иной способ мышления.

+1

проверить обновленный код, я думаю, что вам нужно как GroupProperty (для генерации группы), так и Projections.Property, чтобы сообщить механизму запроса сгенерировать это свойство в элементе выбора – Jaguar

ответ

13

Хорошо, я решил, что решил.

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

Обманывая, однако, я наткнулся на эти классные вещи, называемые 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 станет легче с большим опытом.

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

+0

Это помогло мне!Спасибо Sean – Dunc

+0

Спасибо, куча, тоже помогла! – MadMax1138

1

не работает?

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>() 
+0

Я уже пробовал что-то подобное. Я получаю следующее исключение: Значение «System.Object []» не относится к типу «SearchText» и не может использоваться в этой общей коллекции. – ctrlplusb

+2

Это * должно * работать, если вы вызываете 'List ()'. Вы не получаете список типизированных объектов, но если вы можете иметь дело с 'IList ', вам не нужно будет создавать класс держателя значений для ваших результатов. Это, вероятно, не так чисто, как принятое решение. – dana

Смежные вопросы