如何在NHibernate SqlQuery中生成子类联接?

如何在NHibernate SqlQuery中生成子类联接?,nhibernate,joined-subclass,sql,Nhibernate,Joined Subclass,Sql,我在让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

我在让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; 

但此查询包含SQL错误,因为NHibernate尝试获取字段,这些字段仅在NHibernate还为子类ContentPage添加联接之后才可用。是否可以在不依赖NHibernate恰好使用ie的特定命名样式的情况下以某种方式添加这些连接,手动生成必要的连接?

您可以通过HQL查询接近

因为HQL中没有联合,所以我使用多查询。此外,joined子类意味着每个查询都将有一个到contentpage表的左连接

var q1 = session.CreateQuery(@"
    from    Page p1
    where   p1.Parent is null
    and     p1.UrlSegment=:s1" );

var q2 = session.CreateQuery(@"
    select  p2
    from    Page p2 inner join p2.Parent p1 
    where   p1.Parent is null
    and     p1.UrlSegment=:s1
    and     p2.UrlSegment=:s2" );

var q3 = session.CreateQuery( @"
    select  p3
    from    Page p3 inner join p3.Parent p2
            inner join p2.Parent p1
    where   p1.Parent is null
    and     p1.UrlSegment=:s1
    and     p2.UrlSegment=:s2
    and     p3.UrlSegment=:s3" );

var results = session.CreateMultiQuery()
    .Add<Page>( q1 )
    .Add<Page>( q2 )
    .Add<Page>( q3 )
    .SetParameter("s1", "test1")
    .SetParameter("s2", "test2")
    .SetParameter("s3", "test3")
    .List();

var l1 = (IList<Page>) results[0];
var l2 = (IList<Page>) results[1];
var l3 = (IList<Page>) results[2];

if (l1.Count != 0)  p1 = l1[0];
if (l2.Count != 0)  p2 = l2[0];
if (l3.Count != 0)  p3 = l3[0];

事实上,这将是一个解决办法。不过,这并不是为SQL生成连接问题的一般解决方案,所以我将再等一段时间,然后再接受这个答案。