使用NHibernate;是否可以在子类级别执行限制时查询超类?
例如(psuedo-code的appologies):
Class A
Property Prop1
End Class
Class B
Inherits Class A
Property Prop2
End Class
Class C
Inherits Class A
Property Prop3
End Class
我如何执行如下查询:
from A where Prop1 = 'foo' AND
((if A is B) then B.Prop2 = 'bar' OR
(if A is C) then C.Prop3 = 'bar')
使用Nhibernate.Linq是否可以这样?那么hql还是标准API怎么样?
答案 0 :(得分:3)
由于HQL和ICriteria是域查询工具,我发现很难期待这样的功能。
AFAIK唯一的关键是使用ICriteria的Expression.Sql(),您可以在其中查询超类,但是使用纯sql注入子类特定的片段。在那里,表达式就像
crit.Add(
Expression.Sql(@"(({alias}.DiscrimCol = :subClassADiscrimVal AND {alias}.Col2 = :barVal)
OR ({alias}.DiscrimCol = :subClassBDiscrimVal AND {alias}.Col3 = :barVal))",
new object[] { "subA", "subB", "bar" },
new IType[] { NHibernateUtil.String,NHibernateUtil.String,NHibernateUtil.String } )
);
不好但是有效
另一种方法是使用ISQLQuery
,它至少允许SELECT部分是特定于域的(并使用.AddEntity()
),因此您仍然可以选择托管超类,而WHERE部分包含特定的子类片段
=========更新==========
再想一想,有一种方法可以通过HQL或ICriteria实现这一点,但它更多的是一种解决方法,并且性能较差,因为它涉及子查询。 ICriteria的例子:
nhSes.CreateCriteria(typeof(Super))
.Add(
Restrictions.Disjunction()
.Add(Subqueries.PropertyIn("Id", DetachedCriteria.For(typeof(ChildA))
.SetProjection(Projections.Id())
.Add(Restrictions.Eq("ChildAProp", barVal))))
.Add(Subqueries.PropertyIn("Id", DetachedCriteria.For(typeof(ChildB))
.SetProjection(Projections.Id())
.Add(Restrictions.Eq("ChildBProp", barVal))))
)
我正在查询每个孩子,调整其id,然后选择超类,用投影的子ID限制IN的ID。