NHibernate - как запросить свойства подкласса при возврате суперкласса? - PullRequest
2 голосов
/ 29 июля 2010

Использование 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?

1 Ответ

3 голосов
/ 29 июля 2010

Поскольку HQL и ICriteria являются инструментами доменных запросов, мне сложно ожидать такой функциональности.

AFAIK единственная близкая вещь - это использование Expression.Sql () из ICriteria, где вы запрашиваете суперкласс, но вводите специфичные для подкласса фрагменты с помощью чистого 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 из прогнозируемых дочерних идентификаторов.

...