Search code examples
c#nhibernateicriteria

How to implement NOT IN without establishing relationship


This is similar to this question: NHibernate - Implement "NOT IN" query using ICriteria

But that doesn't work for my solution.

I have an Order:

class Order
{
   DateTime CreatedDate { get; set;} 
   Person CreatedBy { get; set; }
}

and a Person:

class Person
{ 
   string Name { get; set;} // etc.
}

I want to retrieve all people that don't have orders within a date range. The SQL would end up like this:

SELECT *
FROM Person
WHERE Id NOT IN (SELECT PersonId
                 FROM Order
                 WHERE CreatedDate BETWEEN '2012-01-01' and '2012-01-31')

When I query with the solution provided in the above question, it fails if there are 2100 people or more (SQL won't allow that many parameters).

Also I can't add a Orders collection to person because that would involve pulling way too much data (I only want a date range).

How can I do this with NHibernate?


Solution

  • You can use a subquery...

    var peopleWithOrdersInRange = QueryOver.Of<Order>()
        .WhereRestrictionOn(x => x.CreatedDate).IsBetween(fromDate).And(toDate)
        .SelectGroup(x => x.CreatedBy.Id);
    
    var results = Session.QueryOver<Person>()
        .WithSubquery.WhereProperty(x => x.Id).NotIn(peopleWithOrdersInRange)
        .List();
    

    this will produce that exact SQL (with addition of group by people id in the subquery)