2009-03-20 5 views
1

J'ai le problème suivant dans le projet sur lequel je travaille. Chaque transaction dans le système est attribuée à un utilisateur donné. Donc, il y a un grand nombre d'une relation entre les transactions et les utilisateurs, comme ceci:Comment faire une requête pour le plus souvent utilisé plusieurs-à-un dans nhibernate

public class User 
{ 
    public int ID { get; private set; } 
    public string FirstName { get; set; } 
    .... 
} 

public class Transaction 
{ 
    public int ID { get; private set; } 
    public User CreatedBy { get; private set; } 
    ... 
} 

Je cartographié ces entités avec NHibernate pour qu'il y ait un grand nombre à une correspondance entre la transaction et les classes d'utilisateurs. L'objet Utilisateur n'a pas de liste de transactions, mais la transaction contient une référence à l'utilisateur qui l'a créée.

Maintenant, je veux interroger pour récupérer une liste des utilisateurs qui ont créé le plus de transactions, mais je n'arrive pas à comprendre comment obtenir le top 10 des utilisateurs les plus référencés utilisant NHibernate.

Des idées? Je voudrais pouvoir utiliser ICriteria pour compléter ceci plutôt que HQL, mais HQL serait bien si nécessaire.

Mise à jour

J'ai essayé la suggestion de Sirrocco avec la requête comme ...

DetachedCriteria topReferencedUsers = DetatchedCriteria.For(typeof(Transaction)) 
    .SetProjection(Projections.GroupProperty("CreatedBy.Id")) 
    .SetProjection(Projections.Count("CreatedBy.Id").As("pcount")) 
    .AddOrder(Order.Desc("pcount")) 
    .SetMaxResults(10); 

et de construire que la sous-requête ...

GetSession().CreateCriteria(typeof (User)) 
    .Add(Subqueries.PropertyIn("Id", topReferencedUsers)) 
    .List<User>(); 

mais cette sous-requête ne group mais renvoie le nombre total de transactions, qui sont ensuite utilisées comme clause IN pour la requête utilisateur. Si j'ajoute ProjectionList() avec les deux projections, j'obtiens la sortie de la sous-requête que je veux, mais elle échoue parce qu'elle essaie d'exécuter la sortie de deux colonnes dans la clause IN de la requête utilisateur. Comment puis-je obtenir NHibernate pour projeter à la fois l'ID et le Count, mais seulement joindre l'ID?

Mise à jour (2)

J'ai essayé la suggestion de SqlGroupProjection de Sirrocco (merci Sirrocco) mais est venu vide. D'abord il m'a donné des erreurs en disant qu'il ne pouvait pas trouver la propriété pcount, ce qui signifiait que je devais supprimer l'ordre par, ce qui signifie qu'il commandait par un certain horodatage, ce qui ne fonctionnera pas. Mais même avec cela, il ne sort toujours que le nombre de fois que l'utilisateur a été référencé, pas l'identifiant de l'utilisateur avec lequel rejoindre la table Utilisateurs. Des idées? Merci.

+1

Bonjour, J'ai supprimé mon message. Vous devriez avoir plus de chance en demandant au groupe d'utilisateurs nhibernate: http://groups.google.com/group/nhusers?pli=1. Postez ici quand vous avez une réponse, je suis curieux moi-même. Ou vous pourriez commencer une prime. – sirrocco

Répondre

0

Vous pouvez diviser l'opération en deux étapes.

1) Exécutez topReferencedUsers, puis extrayez la projection CreatedBy.Id dans un tableau int en mémoire (puisque vous ne traitez que 10).

2) Puis Execute:

GetSession().CreateCriteria(typeof(User)) 
    .Add(Expression.InG<int>("Id", topTenIdArray)) 
    .List<User>(); 
+0

Ne fonctionne pas. Au moins pour moi ça ne marche pas. J'utilise NHibernate 2.0.1.GA contre SQL Server 2008. Les utilisateurs ne seront pas classés comme topTenIdArray. –

1

Vous pouvez l'essayer pour vous-même et voir si vous obtenez la sortie désirée.

var userIds = this.Session 
    .CreateQuery(@" 
select a.User.Id 
from Transaction as a 
group by a.User 
order by count(a.User) desc") 
    .SetMaxResults(10) 
    .List<int>().ToArray(); 

var users = this.Session.CreateCriteria(typeof(User)) 
    .Add(Restrictions.InG("Id", userIds)) 
    .List<Artist>(); 

return users; 

de la userId que je reçois des premières requêtes sont (90,22,50,55), mais lorsqu'il est passé à la seconde je reçois mes utilisateurs dans 22,50,55,90 ordre.

Questions connexes