2010-07-20 8 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; } 
} 

J'essaie de sélectionner les 5 premiers éléments de recherche en fonction de la somme de leur nombre dans le SearchTextLog. Actuellement, je n'ai pu résoudre ce problème qu'en effectuant une requête pour obtenir les 5 premiers éléments, puis en utilisant le résultat dans une seconde requête. Je me demandais si quelqu'un pouvait me montrer la lumière et m'apprendre comment je pouvais intégrer ces deux requêtes séparées dans une seule unité.NHibernate Les critères sélectionnent les éléments par le groupe et la somme de itemid dans une autre table

Voici ce que j'ai actuellement:

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:

Oh non, je viens de réaliser ma solution actuelle va perdre l'ordre important en des résultats. Donc, je vais certainement devoir incorporer les requêtes. : -/

Edit:

J'ai essayé une mise en correspondance bidirectionnelle trop pour permettre la déclaration suivante, cependant, je ne peux pas l'obtenir pour retourner les articles searchtext. Il se plaint simplement que les propriétés SearchText ne font pas partie d'un regroupement.

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

Excuse mon ignorance, mais Nhibernate est tout à fait nouveau pour moi, et nécessite une manière complètement différente de la pensée.

+1

Vérifiez le code mis à jour, je pense que vous avez besoin à la fois GroupProperty (pour générer grouper par) ainsi que Projections.Property pour dire au moteur de requête de générer cette propriété dans la sélection – Jaguar

Répondre

13

Ok, je pense avoir trouvé une solution.

Ma solution d'origine selon ma question ne fonctionnera pas car NHibernate ne supporte pas encore la possibilité de faire un groupe par propriété sans l'ajouter à la clause select (voir: link text).

Tout en boitant cependant, je suis tombé sur ces choses cool appelées ResultTransformers. En utilisant le transformateur de résultat AliasToBean, Nhibernate mappera automatiquement l'alias que je donne à chaque élément de projection aux propriétés du même nom dans un type que je spécifie. J'ai simplement spécifié mon objet SearchText (cependant, j'ai dû ajouter une propriété TotalSearchCount supplémentaire pour l'élément de projection sum). Il peuplait parfaitement mes objets et les renvoyait. Je suis surpris que ce n'était pas plus facile à faire. Il m'a fallu environ 4 à 5 heures de recherche et de développement pour comprendre celui-ci. J'espère que mon expérience NHibernate sera plus facile avec de plus en plus d'expérience. J'espère que cela aidera quelqu'un d'autre là-bas!

+0

Ça m'a aidé!Merci Sean – Dunc

+0

Merci beaucoup, m'a aidé aussi! – MadMax1138

1

ne fonctionne pas?

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

J'ai déjà essayé quelque chose comme ça. Je reçois l'exception suivante: La valeur "System.Object []" n'est pas de type "SearchText" et ne peut pas être utilisée dans cette collection générique. – ctrlplusb

+2

Ce * devrait * fonctionner si vous appelez 'List ()'. Vous n'obtenez pas une liste d'objets typés, mais si vous pouvez faire face à un 'IList ', vous n'aurez pas à créer une classe de détenteur de valeur pour vos résultats. Ce n'est probablement pas aussi propre que la solution acceptée. – dana

Questions connexes