Hibernate Следующая / предыдущая карта братьев и сестер - PullRequest
0 голосов
/ 23 февраля 2009

Я использую nHibernate для отображения объекта, очень похожего на .NET System.Web.SiteMapNode. Чтобы мой объект оставался похожим на этот .NET-объект, я бы хотел, чтобы он содержал сложные свойства ParentNode, PreviousSibling, NextSibling и ChildNodes.

Таблица выглядит примерно так и может быть изменена:

  • ID (int)
  • Заголовок (строка)
  • Описание (строка)
  • Ключ (строка)
  • ParentNodeId (int)
  • OrdinalPosition (int)
  • ReadOnly (bool)
  • URL (строка)

У меня могут быть некоторые другие свойства, которые не нужны для имитации объекта .NET SiteMapNode (например, isExternal bool), но я думаю, что они не имеют значения для этого вопроса.

Мое текущее отображение выглядит так:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="AthletesCafe.Core.Domain.System.SiteMap" assembly="AthletesCafe.Core">
<class name="SiteMapNode" table="SiteMapNode" lazy="true" >

<id name="ID" type="Int32" unsaved-value="0">
  <column name="ID" not-null="true" unique="true" index="PK_SiteMapNode"/>
  <generator class="identity" />
</id>

<property name="Title" column="Title" type="String" length="255" not-null="true" />
<property name="Description" column="Description" type="String" not-null="false" />

<property name="Url" column="Description" type="String" not-null="true"  />

<property name="SiteMapKey" column="SiteMapKey" type="String" not-null="true" length="255"  />

<property name="OrdinalPosition" column="OrdinalPosition" type="Int32" not-null="true" />

<property name="ReadOnly" column="ReadOnly" not-null="true" type="System.Boolean" />

<property name="IsExternal" column="IsExternal" not-null="true" type="System.Boolean" />

<many-to-one name="ParentNode" column="ParentNodeId" class="AthletesCafe.Core.Domain.System.SiteMap.SiteMapNode, AthletesCafe.Core" 
             access="field.pascalcase-underscore" not-null="false" />
<many-to-one name="PreviousNode" column="ParentNodeId" class="EatMyTrainer.Core.Domain.SiteMap.SiteMapNode, EatMyTrainer.Core" not-null="false" /></hibernate-mapping>

Отображение ParentNode является простым, поскольку оно должно быть простым отображением «многие к одному». Вот код, который у меня есть (непроверенный, но я считаю, что он правильный):

<many-to-one name="ParentNode" column="ParentNodeId" class="AthletesCafe.Core.Domain.System.SiteMap.SiteMapNode, AthletesCafe.Core" 
             access="field.pascalcase-underscore" not-null="false" />

Отображение для дочерних узлов должно быть простой сумкой, которая вернет все объекты SiteMapNode, у которых ParentNodeId равен текущему идентификатору. Я еще не написал эту сумку, но я считаю, что это не такая уж большая проблема.

Проблема, которую я не могу решить, заключается в том, как настроить свойства Next / Previous Sibling. Эти объекты могут быть получены из следующей формулы для каждого узла:

  • PreviousSibling: имеет тот же ParentNode (ParentNodeId), что и текущий объект, и его OrdinalPosition должно быть на единицу меньше, чем OrdinalPosition текущего объекта.
  • NextSibling: имеет тот же ParentNode (ParentNodeId), что и текущий объект, и его OrdinalPosition должно быть на единицу больше, чем OrdinalPosition текущего объекта.

Я думаю, что это достижимо с помощью формального атрибута в сопоставлении «многие к одному». Это возможно? Я не нашел хорошего примера того, как это работает.

Ответы [ 2 ]

0 голосов
/ 25 февраля 2009

Я считаю, что Стюарт прав в этой ситуации. Это невозможно сделать для сопоставления «многие к одному». Если бы NHibernate предоставил способ сделать, где оговорка об этом отображении, у меня может быть шанс.

Другое возможное решение, хотя и неэффективное, - создать сумку, в которой используется полевой установщик. Открытое свойство, которое будет следующим / предыдущим параметром, все равно будет возвращать ссылку на объект (в отличие от перечислимого). В геттере он будет просто ссылаться на первую позицию перечислимого в поле. Ленивая загрузка была бы идеальной, потому что NHibernate не смог бы загрузить этот объект за один раз с начальной загрузкой объекта. У вас будет штраф за доступ к этому объекту каждый раз.

Полагаю, оба решения имеют одинаковый штраф.

0 голосов
/ 24 февраля 2009

Я не думаю, что то, что вы просите, строго возможно (хотя мне было бы очень интересно увидеть решение, если оно есть). Был бы относительно простой обходной путь, но NHibernate не поддерживает двунаправленные сопоставления «один ко многим» с индексированными коллекциями на множестве концов.

Единственное, что приходит на ум, немного уродливо: родительский объект должен сохранять свою собственную индексную карту (с ключом OrdinalPosition) для каждого дочернего объекта. На ребенка сделать что-то вроде:

public SiteMapNode NextSibling()
{
    return this.Parent.NextSibling(this);
}
...