我在让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; }
}
现在,想象一个简单的field-for-field,join-subclass映射到数据库。我想出了这个查询来查找路径/ 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正在使用的特定命名样式(即,手动生成必要的连接)?
答案 0 :(得分:0)
你可以接近HQL查询。
由于HQL中没有UNION,我使用MultiQuery。 join-subclass也意味着每个查询都有一个LEFt JOIN到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];