私の問題をより簡単に説明するために、非常に基本的な多対多の関係を示す次の架空の例を作成します。Carは多くのPartを持つことができ、Partは多くのCarに属することができます。
データベース スキーマ:
CAR_TABLE
---------
CarId
ModelName
CAR_PARTS_TABLE
---------------
CarId
PartId
PARTS_TABLE
-----------
PartId
PartName
クラス:
public class Car
{
public int CarId {get;set;}
public string Name {get;set;}
public IEnumerable<Part> Parts {get;set;}
}
public class Part
{
public int PartId {get;set;}
public string Name {get;set}
}
この非常に単純なモデルを使用して、検索対象のパーツのリストからすべてのパーツが割り当てられている車を取得したいと考えています。
たとえば、PartIds の配列があるとします。
var partIds = new [] { 1, 3, 10};
データベース呼び出しに関して、次の c# コードを模倣したいと考えています。
var allCars = /* code to retrieve all cars */
var results = new List<Car>();
foreach (var car in allCars)
{
var containsAllParts = true;
foreach (var carPart in car.Parts)
{
if (false == partIds.Contains(carPart.PartId))
{
containsAllParts = false;
break;
}
}
if (containsAllParts)
{
results.Add(car);
}
}
return results;
明確にするために: partIds 配列から指定されたすべてのパーツを持つ車を取得したいと考えています。
次のクエリがあります。これは、partIds 配列内の各 ID に対してサブクエリを作成し、結果ごとに IsIn クエリを実行するため、非常に非効率的です。このクエリを実行するためのより効率的な方法を見つけたいと切望しています。
Car carAlias = null;
Part partAlias = null;
var searchCriteria = session.QueryOver<Car>(() => carAlias);
foreach (var partId in partIds)
{
var carsWithPartCriteria = QueryOver.Of<Car>(() => carAlias)
.JoinAlias(() => carAlias.Parts, () => partAlias)
.Where(() => partAlias.PartId == partId)
.Select(Projections.Distinct(Projections.Id()));
searchCriteria = searchCriteria
.And(Subqueries.WhereProperty(() => carAlias.Id).In(carsWithPartCriteria));
}
var results = searchCriteria.List<Car>();
NHibernate を使用してこの種のクエリを実行する適切な方法はありますか?