2012-08-08 52 views
0

這類似於這樣的問題:NHibernate - Implement "NOT IN" query using 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?

+0

爲什麼不使用HQL或SQL? – Rippo 2012-08-08 14:39:39

+0

我會很高興HQL,但查詢更易於維護。據我所知,SQL不會讓你輕鬆地將你的查詢映射到具有NHibernate的實體。 – 2012-08-09 11:22:25

回答

3

您可以使用子查詢...

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在子查詢)

+0

偉大的解決方案。非常感謝你的幫助 – 2012-08-09 03:20:24

2

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).

據我所知,您在將訂單集合傳遞給查詢之前,先將訂單集合中的人實現。

這裏是一個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(); 
+0

這看起來像一個很好的解決方案,除了IQueryable 沒有Contains方法。 – 2012-08-09 03:13:55

+0

確定[Queryable.Contains 方法(IQueryable的,TSource)(http://msdn.microsoft.com/en-us/library/bb338641)? – hazzik 2012-08-09 07:43:56

+0

原諒我; Resharper讓我感到困惑。真正的問題是它期望在第二個linq語句的where子句中使用IQueryable 。 – 2012-08-09 11:19:20