这类似于这个问题: NHibernate - 使用 ICriteria 实现 "NOT IN" 查询
但这不适用于我的解决方案。
我有一个订单:
class Order
{
DateTime CreatedDate { get; set;}
Person CreatedBy { get; set; }
}
和一个人:
class Person
{
string Name { get; set;} // etc.
}
我想检索所有在某个日期范围内没有订单的用户。 SQL 的结局是这样的:
SELECT *
FROM Person
WHERE Id NOT IN (SELECT PersonId
FROM Order
WHERE CreatedDate BETWEEN '2012-01-01' and '2012-01-31')
当我使用上述问题中提供的解决方案进行查询时,如果有 2100 人或更多人,它将失败(SQL 不允许那么多参数)。
此外,我无法向人员添加订单集合,因为这将涉及提取太多数据(我只想要一个日期范围)。
如何使用 NHibernate 执行此操作?
您可以使用子查询...
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();
这将生成确切的 SQL(在子查询中添加按人员 ID 分组)
当我使用上述问题中提供的解决方案进行查询时,如果有 2100 人或更多人,它将失败(SQL 不允许那么多参数)。
据我了解,在将订单收集传递到查询之前,您确实会通过订单收集来具体化人员。
这是一个应该可以工作的 linq 查询
var unwantedPersons =
from order in session.Query<Order>()
where order.CreatedDate >= startDate &&
order.CreatedDate <= endDate
select order.CreatedBy.Id // NOTE: do not add .ToList() or .ToArray() here.
// It *should be* IQueryable<Person>
var personsWitoutOrders =
(from person in session.Query<Person>()
where !unwantedPersons.Contains(person.Id)
select person).ToArray();