【问题标题】:How to implement NOT IN without establishing relationship如何在不建立关系的情况下实施 NOT IN
【发布时间】:2012-08-08 14:17:00
【问题描述】:

这类似于这个问题:NHibernate - Implement "NOT IN" query using ICriteria

但这不适用于我的解决方案。

我有一个订单:

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 不会允许那么多参数)。

此外,我无法向人员添加 Orders 集合,因为这会涉及方式提取太多数据(我只想要一个日期范围)。

如何使用 NHibernate 做到这一点?

【问题讨论】:

  • 我可以使用 HQL,但查询更易于维护。据我了解,SQL 不会让您轻松地将查询映射到具有 NHibernate 的实体。

标签: c# nhibernate icriteria


【解决方案1】:

您可以使用子查询...

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 分组)

【讨论】:

  • 很好的解决方案。非常感谢您的帮助
【解决方案2】:

当我使用上述问题中提供的解决方案进行查询时,如果有 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();

【讨论】:

猜你喜欢
  • 2018-12-27
  • 2014-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-13
  • 1970-01-01
相关资源
最近更新 更多