#nhibernate #queryover
#nhibernate #выполнение запроса
Вопрос:
У меня есть следующий запрос NHibernate с использованием подзапроса:
NHContext.Session.QueryOver<Item>()
.WithSubquery.WhereProperty(x => x.ItemId).In(QueryOver.Of<Foo>().Where(x => x.AFlag).Select(x => x.ItemId))
.WithSubquery.WhereProperty(x => x.ItemId).In(QueryOver.Of<Bar>().Where(x => x.AFlag).Select(x => x.Item))
.Future<Item>();
При этом выполняется следующий SQL:
SELECT *
FROM item this_
WHERE this_.ItemId in (SELECT this_0_.ItemId as y0_
FROM Foo this_0_
WHERE this_0_.AFlag = 1 /* @p0 */)
and this_.ItemId in (SELECT this_0_.ItemId as y0_
FROM Bar this_0_
WHERE this_0_.AFlag = 1 /* @p0 */)
Я бы хотел, чтобы он использовал ИЛИ так, например:
SELECT *
FROM item this_
WHERE this_.ItemId in (SELECT this_0_.ItemId as y0_
FROM Foo this_0_
WHERE this_0_.AFlag = 1 /* @p0 */)
or this_.ItemId in (SELECT this_0_.ItemId as y0_
FROM Bar this_0_
WHERE this_0_.AFlag = 1 /* @p0 */)
Я знаю, что могу сделать это в критериях, выполнив что-то вроде:
var disjunction = new Disjunction();
disjunction.Add(Subqueries.PropertyIn("ItemId",
DetachedCriteria.For<Foo>()
.SetProjection(Projections.Property("ItemId"))
.Add(Restrictions.Eq("AFlag", 1))
));
Но было интересно, есть ли более простой способ сделать это с помощью QueryOver и избежать использования строк для имен свойств.
Спасибо за любую помощь.
Ответ №1:
Для менее распространенной дизъюнкции (или), я думаю, вам нужно использовать Subqueries.WhereProperty<>
вместо WithSubquery
Session.QueryOver<Item>()
.Where(Restrictions.Disjunction()
.Add(Subqueries.WhereProperty<Item>(x => x.ItemId).In(QueryOver.Of<Foo>().Where(x => x.AFlag).Select(x => x.ItemId)))
.Add(Subqueries.WhereProperty<Item>(x => x.ItemId).In(QueryOver.Of<Bar>().Where(x => x.AFlag).Select(x => x.Item))))
.Future<Item>();