2010-11-24 10 views
3

Quelle est la meilleure façon de sélectionner une liste (distincte) d'entités parentes ayant une collection enfant contenant des correspondances pour TOUTES les entrées d'une liste de paramètres d'enfants?Comment faire correspondre tous les enfants utilisant hql

je joue la « toute » version de ma recherche comme ceci:

select p.Id, p.Name from parent p 
where exists(from p.Children c where c in (:childList)) 

Cependant, je suis un peu perplexe sur la meilleure façon d'exécuter la version « tout » de cette recherche. Actuellement, je crée hql à la volée pour chaque enfant que je suis intéressé à faire correspondre; quelque chose comme ceci:

select p.Id, p.Name from parent p 
where :child1 in elements(p.Children) 
and :child2 in elements(p.Children) 
-- etc... 

Je ne peux pas m'empêcher de penser qu'il y a une meilleure façon de le faire; Est-ce que quelqu'un peut-il me montrer la bonne direction?

Pour référence, j'utilise une question intéressante NHibernate 2.1.2

+2

Cela semble essentiellement comme la division relationnelle, mais avec des paramètres au lieu d'une table. Voir http://www.simple-talk.com/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division/ –

+0

@Mauricio: intéressant, je n'ai pas entendu parler de cette terminologie avant, merci pour la référence. – DanP

Répondre

2

et je ne trouve pas de réponse facile. Des tentatives simples utilisant "tous les éléments (p.Children) dans (: childList)" n'ont pas réussi à produire un SQL valide. Ce monstre a fini par travailler ...

var query = session.CreateQuery("select p from Parent p join p.Children c where c in (:childList) group by p.Id, p.Name having count(p) = :childListSize"); 
var children = new[] {session.Load<Child>(1),session.Load<Child>(2),session.Load<Child>(3)}; 
query.SetParameterList("childList", children); 
query.SetParameter("childListSize", children.Length); 

Brisons le HQL ...

select p from Parent p 
join p.Children c 
where c in (:childList) 
group by p.Id, p.Name 
having count(p) = :childListSize 

Nous sommes en train de créer une jointure avec les enfants, ce qui produit plusieurs lignes, sélectionner les lignes où la child est dans le childList, en groupant par le parent, et en voyant si nous avons obtenu le nombre prévu de rangées et en renvoyant seulement ces parents. Ouf!

Notez que vous devez spécifier explicitement toutes les propriétés du groupe. Sinon NH ne comprend que l'ID et le groupe échoue. BTW - J'ai couru ceci contre NH3, bien que je ne puisse pas penser à aucune raison que cela ne fonctionnerait pas avec NH2.1.2.

+0

Approche intéressante - Je vais essayer et voir à quoi ressemblent les numéros de performance. Incidemment, la spécification des propriétés dans le groupe n'est pas un gros problème, comme je le fais déjà dans l'instruction select (renvoyant un dto plutôt qu'une entité complète) – DanP

+0

Cela semble fonctionner assez efficacement pour mes cas de test; Bien que cela vous amène à vous demander pourquoi il n'y a pas une sorte de "tout en" construire pour hql/sql pour couvrir de tels cas :) – DanP

+0

Ce serait pratique, non? Quand j'ai commencé à creuser, j'ai été surpris que SQL ne supporte pas quelque chose comme "(list1) in (list2)". Je pense que ma technique est assez générale pour qu'on puisse l'ajouter à HQL. L'équipe de NHibernate est toujours prête à accepter un patch. :) –

1

vous pourriez interroger l'enfant et sélectionnez le parent, tant que l'association existe, quelque chose comme ça ...

select distinct c.Parent.Id, c.Parent.Name from Child c 
where c in (:childList)) 
+0

Ceci est certainement une option pour certains de mes cas, mais pas toutes mes entités ont une relation bidirectionnelle - donc cette méthode ne fonctionnerait pas pour ceux-ci. – DanP

+0

Il me semble étrange d'avoir un domaine/une cartographie des collections qui sont mappées et les propriétés many-to-one correspondantes ne le sont pas. – Jaguar

+0

Jaguar; cette méthode présente également un léger inconvénient, car j'essaie de généraliser plusieurs recherches en utilisant un modèle commun; mes instructions select diffèrent par recherche avec cette méthode, en utilisant l'approche de James c'est un non-problème. – DanP