Загрузка коллекции в базовый класс из присоединенного подкласса с помощью NHibernate

У меня есть класс с некоторыми свойствами и набор имен, например, так:

public class A : BaseObject
{
    private Int32 zindex;
    private Int32 atNmNr;
    private IList<G020_Namen> names = new List<G020_Namen>();
}

Тогда у меня есть класс B, который расширяет класс A примерно так:

public class B : A
{
    private Int32 zindex;
    private String etiketnaam;

    public B() { }

    public virtual Int32 Zindex
    {
        get { return zindex; }
        set { zindex = value; }
    }
}

А и В связаны по своим первичным ключам. Класс B отображается в файле отображения класса A как объединенный подкласс следующим образом:

    <class name="A" table="A" lazy="true" >
<cache usage="read-write"/>
<id name="Zindex" type="Int32" >
  <column name="Zindex" />
  <generator class="assigned" />
</id>
<property name="AtNmNr" type="Int32">
  <column name="ATNMNR"/>
</property>
<bag name="Namen" table="G020_Namen" inverse="true" cascade="all-delete-orphan" fetch="select" lazy="false" >
  <cache usage="read-write"/>
  <key>
    <column name="NMNR" />
  </key>
  <one-to-many class="G020_Namen" />
</bag>
<joined-subclass name="B" table="B" >
  <key column="Zindex" />
  <property name="Zindex" type="Int32">
    <column name="Zindex"/>
  </property>
  <property name="Etiketnaam" type="String">
    <column name="Etiketnaam"/>
  </property>
</joined-subclass>

Теперь, если я хочу получить записи для A, используя критерии, он работает нормально, и коллекция имен загружается. Но если я хочу получить записи для подкласса B, коллекция имен не загружается (в базовый класс A).

Затем я попытался добавить CreateCriteria для сопоставления коллекции:

        ICriteria crit = session.CreateCriteria(typeof(B))
            .CreateCriteria("Names", NHibernate.SqlCommand.JoinType.InnerJoin);

Это приводит к следующему SQL:

SELECT B.Zindex, B.Etiketnaam, G020_Namen.NMNAAM FROM B
INNER JOIN A ON B.Zindex = A.Zindex 
INNER JOIN G020_Namen ON B.Zindex = G020_Namen.NMNR

Поэтому он пытается связать таблицу с именами с первичным ключом таблицы подклассов B, а не с внешним ключом базовой таблицы A. Это должно быть:

SELECT B.Zindex, B.Etiketnaam, G020_Namen.NMNAAM FROM B
INNER JOIN A ON B.Zindex = A.Zindex 
INNER JOIN G020_Namen ON A.AtNnNr = G020_Namen.NMNR

Вопрос в следующем: возможно ли заставить NHibernate загружать коллекцию из базового класса из подкласса с помощью операторов ICriteria?

Спасибо,

Мартин ван дер Линден.

1 ответ

Ваши ожидания неверны:

INNER JOIN G020_Namen ON A.AtNnNr = G020_Namen.NMNR

AtNnNr даже не отображается. Если вы имели в виду ATNMNR, его не следует использовать в соединении, потому что это простой столбец без FK. Пожалуйста, добавьте больше информации о первоначальной проблеме:

Но если я хочу получить записи для подкласса B, коллекция имен не загружается (в базовый класс A).

Что не загружается? Имена или Б? Не загружается как? Исключение или пустая коллекция?

Как примечание, ваше отображение не является оптимальным.

  • Похоже, вы хотите, чтобы ваша коллекция загружалась с нетерпением (lazy="false"). В этом случае используйте fetch="join" вместо fetch="select" чтобы избежать дополнительного SELECT.

  • Вам не нужно <property name="Zindex" type="Int32"> в классе B. Вы можете получить это из базового класса, если сделаете защищенным zindex.

Другие вопросы по тегам