クエリにサブクラスの結合がないため、NHibernateで実際にエラーなしで実行されるSQLクエリを生成するのに問題があります。
この最小限の例を見てみましょう。
class Page
{
public virtual int Id { get; set; }
public virtual string UrlSegment { get; set;}
public virtual Page Parent { get; set; }
}
class ContentPage
{
public string Content { get; set; }
}
ここで、これをデータベースに単純にフィールドごとに結合したサブクラスマッピングを想像してみてください。パス/page/ page2 / page3に沿ってすべてのページを見つけるために、このクエリを思いつきました。
SELECT p1.* FROM page p1
WHERE
p1.parent IS NULL
AND p1.hierarchysegment = 'test'
UNION
SELECT p2.* FROM page p1
JOIN page p2 ON p2.parent = p1.id
WHERE
p1.parent IS NULL
AND p1.hierarchysegment = 'test'
AND p2.hierarchysegment = 'test2'
UNION
SELECT p3.* FROM page p1
JOIN page p2 ON p2.parent = p1.id
JOIN page p3 ON p3.parent = p2.id
WHERE
p1.parent IS NULL
AND p1.hierarchysegment = 'test'
AND p2.hierarchysegment = 'test2'
AND p3.hierarchysegment = 'test3'
;
さて、これはクエリを実行するときに問題なく機能するようです。SqlQueryを使用してこれを生成してみましょう(簡略化され、最初の部分のみが表示されます)。
IQuery q = session.CreteSQLQuery("SELECT {p0.*} FROM page {p0} WHERE {p0.Parent} IS NULL" +
"AND {p0.HierarchySegment} = 'page1'", "p0", typeof(Page));
これにより、次のクエリが生成されます。
SELECT p0.ID AS id0_0_,
p0.enabled AS enabled0_0_,
p0.linktext AS linktext0_0_,
p0.hierarchysegment AS hierarch4_0_0_,
p0.tooltiptext AS tooltipt5_0_0_,
p0.PARENT AS parent0_0_,
p0_1_.content AS content1_0_,
CASE
WHEN p0_1_.ID IS NOT NULL
THEN 1
WHEN p0.ID IS NOT NULL
THEN 0
END AS clazz_0_
FROM page p0
WHERE parent0_0_ IS NULL
AND hierarch4_0_0_ = page1;
ただし、NHibernateがサブクラスContentPageの結合も追加した後にのみ使用可能なフィールドをフェッチしようとするため、このクエリにはSQLエラーが含まれています。NHibernateがたまたま使用している特定の命名スタイルに依存せずに(つまり、必要な結合を手動で生成する)、どういうわけかこれらの結合を追加することは可能ですか?