NHibernate – как запрашивать свойства подкласса при возврате суперкласса?

Использование NHibernate; можно ли запросить суперкласс при выполнении ограничений на уровне подкласса?

Например (приносим извинения за псевдокод):

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 критериев?


person DanP    schedule 28.07.2010    source источник


Ответы (1)


Поскольку 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))))
        )

я запрашиваю каждого ребенка, проецирую его идентификатор, а затем выбираю суперкласс, ограничивая идентификаторы с помощью IN из прогнозируемых дочерних идентификаторов.

person Jaguar    schedule 29.07.2010
comment
Спасибо за это; к сожалению, нет более чистого подхода, кроме использования собственного sql. Интересно, будет ли выполнение операции объединения лучшим вариантом? - person DanP; 29.07.2010