2010-11-24 6 views
3

Каков наилучший/предпочтительный способ выбора (выделенного) списка родительских объектов, у которого есть дочерняя коллекция, содержащая совпадения для ВСЕХ записей в списке параметров детей?Как сопоставить всех детей с помощью hql

я выступаю «любую» версию моего поиска, как это:

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

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

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

Я не могу не думать, что есть лучший способ сделать это; Может кто-то указать мне верное направление?

Для справки, я использую NHibernate 2.1.2

+2

Это, кажется, в основном, как реляционного деления, но с параметрами вместо таблицы. См. Http://www.simple-talk.com/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division/ – 2010-11-25 01:37:18

+0

@Mauricio: интересно, я не слышал об этой терминологии раньше, спасибо за ссылку. – DanP 2010-11-25 13:52:07

ответ

2

Интересный вопрос, и я не нашел простой ответ. Простые попытки с использованием «всех элементов (p.Children) в (: childList)» не привели к действительному SQL. Этот монстр в конечном итоге работает ...

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

Давайте вспыхивают HQL ...

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

Мы создаем внутреннее соединение с детьми, выпускающий несколько строк, выбирая те строки, где child находится в childList, группируется родителем и видит, получили ли мы ожидаемое количество строк и только вернули эти родители. Уф!

Обратите внимание, что вам необходимо явно указать все свойства в группе. В противном случае NH включает в себя только Id и группу.

BTW - Я провел это против NH3, хотя я не могу придумать, почему он не будет работать с NH2.1.2.

+0

Интересный подход - я дам этот снимок и посмотрю, как выглядят номера производительности. Кстати, определение свойств в группе не имеет большого значения, поскольку я уже делаю это в инструкции select (возвращаю dto, а не полностью выдутый объект). – DanP 2010-11-25 01:54:20

1

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

select distinct c.Parent.Id, c.Parent.Name from Child c 
where c in (:childList)) 
Смежные вопросы