QueryOver Or with Subquery

Gunner picture Gunner · Oct 31, 2011 · Viewed 11k times · Source

IHave the following NHibernate query using a subquery:

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

This runs the following 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 */)

I would like it to use OR so for example:

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 */)

I know I can do it in Criteria by doing something like:

var disjunction = new Disjunction();
disjunction.Add(Subqueries.PropertyIn("ItemId", 
     DetachedCriteria.For<Foo>()
     .SetProjection(Projections.Property("ItemId"))
     .Add(Restrictions.Eq("AFlag", 1))
));

But was wondering if there was an easier way to do it via QueryOver, and avoiding using strings for property names.

Thanks for any help.

Answer

dotjoe picture dotjoe · Oct 31, 2011

For the less common disjunction(or) I think you need to use the Subqueries.WhereProperty<> instead of 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>();