Search code examples
c#nhibernatequeryover

Convert SQL to NHibernate Fluent syntax for Fetchplan


How would I express the following in terms of a fluent nhibernate syntax for a fetchplan

select *
from Person a
where 
(
 (Male = 0) or
 ((Male = 1) and exists (select * from Staff where PersonId = XXX and EmployeeId = YYY))
)
and PersonId = XXX

The best I can manage is this but it doesn't even compile.

Person pers = null;
Staff s = null;

var subquery = QueryOver.Of<Staff>(() => s)
                        .Where(() => s.Employee.Id == YYY)
                        .And(() => s.Person.Id == XXX);

var query = session.QueryOver<Person>()
                   .Where(NHibernate.Criterion.Restrictions.Disjunction()
                   .Add(Subqueries.WhereProperty<Person>(a => !a.Male))
                   .Add(Subqueries.WhereProperty<Person>(a => a.Male))
                   .Add(Subqueries.WhereExists(subquery)))
                   .Where(() => pers.Id == XXX);

Solution

  • The QueryOver syntax should be like this:

    Person pers = null;
    Staff s = null;
    
    var subquery = QueryOver
        .Of<Staff>(() => s)
        .Where(() => s.Employee.Id == YYY)
        .And(() => s.Person.Id == XXX)
        // any SELECT clause, including the sub select, must return something
        .Select(sub => sub.Id)
        ;
    
    var query = session
        // let's use alias we've already declared above
        .QueryOver<Person>(() => pers)
    
        // the first condition
        .Where(
    
            // let's simplify the stuff 
            // instead of:   (IsMale OR (!IsMale AND exists)
            // use the same: (IsMale OR exists)
    
            Restrictions.Disjunction()
                .Add(() => pers.Male)  // alias pers
                .Add(Subqueries.Exists(subquery.DetachedCriteria))
        )
        // the second top level condition
        .And(() => pers.ID == XXX) // alias pers
        ;
    

    And now query.List<Person>().SingleOrDefault() should return Male or Staff guy.