Как реализовать поисковый запрос в NHibernate 3 (используя NHibernate.Linq) - PullRequest
0 голосов
/ 01 июня 2011

Я пытаюсь построить поисковый запрос с использованием NHibernate, который будет фильтровать параметры из нескольких разных таблиц и привести к несколько разумному SQL, который может использовать преимущества отложенной загрузки NHibernate.Читая различные советы онлайн, кажется, что самый последний и лучший способ сделать это - использовать объект QueryOver для условного добавления используемых параметров, как в следующем фрагменте:

Hibernate.Criterion.QueryOver<Models.Site, Models.Site> query = NHibernate.Criterion.QueryOver.Of<Models.Site>();

if (!string.IsNullOrEmpty(state))
                query = query.WhereRestrictionOn(r => r.State.StateName).IsInsensitiveLike("%" + state + "%");

if (startDate.HasValue)
                    query = query.Where(r => r.Events
                                            .Where(e=>e.EventDate >= startDate.Value)
                                            .Count() > 0
                                    );

return query.GetExecutableQueryOver(currentSession).Cacheable().List();

(у события есть внешний ключ к сайту)

У меня два вопроса: как фильтровать дочерние объекты, а не только родительский?Пример кода выше дает мне все сайты с совпадающими событиями, но на этом сайте я хочу только совпадающие события.Если я должен использовать соединение или подзапрос, как?Меня смущает поддержание моей древовидной иерархии с отложенной загрузкой через объединение или подзапрос.

Редактировать: на этот вопрос дан ответ.Спасибо, псуса! Как добавить предложение или?Я нашел ссылку на объект Disjunction, но, похоже, он недоступен при использовании метода QueryOver.

Редактировать: я хочу получить список сайтов (объект верхнего уровня), отфильтрованных покритерии сайта, и каждый сайт должен иметь свой список событий, отфильтрованный по критериям события.

Я ожидаю, что он генерирует SQL, как показано ниже:

SELECT *
FROM [site] s
    LEFT JOIN [event] e ON s.siteID = e.siteID
WHERE e.eventDate > @eventDate
    AND (s.stateCd = @state OR s.stateName LIKE @state)

Ответы [ 2 ]

0 голосов
/ 27 июня 2011

При использовании псевдонима соединения, предложенного psousa, вы получите странную комбинацию структуры объекта и структуры строки с объектами верхнего уровня, дублирующимися дочерними объектами, которые к ним прикреплены.Чтобы получить результаты, которые я искал, вы можете использовать TransformUsing и DistinctRootEntityResultTransformer, как показано в следующем коде:

    Site siteAlias = null;
    Event eventAlias = null;

    var results = currentSession.QueryOver<Site>(() => siteAlias)
            .JoinAlias(m => m.Event, () => eventAlias)
            .Where(() => eventAlias.EventDate > eventDate)
            .Where(() => siteAlias.StateCd == state || Restrictions.On(() => siteAlias.StateName).IsLike(state))
            .TransformUsing(new NHibernate.Transform.DistinctRootEntityResultTransformer())
            .List();
0 голосов
/ 01 июня 2011

Я бы сделал этот запрос так:

//use aliases. Optional but more practical IMHO 
Site siteAlias = null;
Event eventAlias = null;

//use JoinAlias instead of JoinQueryOver to keep the condition at the "Site" level
var results = Session.QueryOver(() => siteAlias)
        .JoinAlias(m => m.Event, () => eventAlias)
        .Where(() => eventAlias.EventDate > eventDate)
        .Where(() => siteAlias.StateCd == state || Restrictions.On(() => siteAlias.StateName).IsLike(state))
        .List();

Вы упомянули класс Disjunction, и он может фактически использоваться с QueryOver, например:

var disjunction= new Disjunction();
disjunction.Add(() => siteAlias.StateCD == state);
disjunction.Add(Restrictions.On(() => siteAlias.StateName).IsLike(state));

Запрос QueryOver будет:

var results = Session.QueryOver(() => siteAlias)
        .JoinAlias(m => m.Event, () => eventAlias)
        .Where(() => eventAlias.EventDate > eventDate)
        .Where(disjunction)
        .List();
...