代码之家  ›  专栏  ›  技术社区  ›  DanP

如何在返回超类的同时查询子类属性?

  •  2
  • DanP  · 技术社区  · 14 年前

    使用NHibernate;在子类级别执行限制时,是否可以查询超类?

    例如(psuedo代码的近似值):

    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或者criteriaapi呢?

    1 回复  |  直到 14 年前
        1
  •  3
  •   Jaguar    14 年前

    由于HQL和ICriteria是域查询工具,我发现很难期望有这样的功能。

    唯一接近的方法是使用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 它至少允许选择部分是特定于域的(并且使用 .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))))
            )