0

これは次の質問に似ています: 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 コレクションを person に追加することはできません (日付範囲のみが必要です)

NHibernate でこれを行うにはどうすればよいですか?

4

2 に答える 2

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が生成されます(サブクエリにgroup by people idが追加されます)

于 2012-08-08T18:12:30.973 に答える
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).

As I understand you do materialize persons with orders collection before passing it into a query.

Here is a linq query that should work

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();
于 2012-08-08T18:04:03.710 に答える