NHibernate QueryOver Where Or Or для собственности и вложенной коллекции - PullRequest
0 голосов
/ 02 июня 2019

У меня есть классы Foo и Bar

class Foo {
    string Name;
    IList<Bar> Bars;
}

class Bar {
    string Name;
}

У меня есть вход q, и я хочу написать запрос NHibernate, который возвращает список Foo объектов, если Foo.Name содержит q или любой из Bars объектов 'Name s содержит q.

Я знаю, как я могу делать отдельные запросы, но я не уверен, как объединить его в 1 с оператором OR между ними. По сути, если объект Foo содержит q в своем имени или в любом из его Bars имен, я хочу, чтобы объект Foo находился в выходных данных.

this.sessionFactory.GetCurrentSession()
    .QueryOver<Foo>()
    .Where(x => x.Name.IsInsensitiveLike(q))
    .List();
this.sessionFactory.GetCurrentSession()
    .QueryOver<Foo>()
    .JoinQueryOver<Bar>(x => x.Bars)
    .Where(x => x.Name.IsInsensitiveLike(q))
    .List();

1 Ответ

1 голос
/ 04 июня 2019

Давайте начнем с объявления псевдонимов, для последующего использования в запросах

Foo foo = null;
Bar bar = null;

Первый подход сейчас состоит в том, чтобы присоединиться к коллекции (и получить немного некрасивые результаты с умноженным родителем для каждого соответствующего потомка)

.QueryOver<Foo>(() => foo)
.JoinQueryOver<Bar>(x => x.Occupations, () => bar)
.Where(x => foo.Name.IsInsensitiveLike(q)
         || bar.Name.IsInsensitiveLike(q))

Это будет работать, но может вернуть некоторые строки, повторяющие родительский Foo, в случае, если есть больше совпадающих дочерних элементов Bar ...

Foo1, Bar1
Foo1, Bar2

Чтобы получить только чистый родительский набор результатов, нам нужно заменить JOIN подзапросом

.QueryOver<Foo>(() => foo)
.Where(Restrictions
    .Or(
        Restrictions.Where(() => foo.Name.IsInsensitiveLike(q)),
        Subqueries
            .WhereProperty(() => foo.ID)
                .In(QueryOver.Of<Bar>(() => bar)
                    .Where(() => bar.Name.IsInsensitiveLike(q))
                    .Select(y => bar.Foo.ID)
                )
    )
)

Это также предполагает, что дочерний Bar имеет обратную ссылку на Foo ..., что является абсолютно законным и деловымподдержка модели домена.

...