0

我正在使用 nHibernate 映射一个与 .NET 的 System.Web.SiteMapNode 非常相似的对象。为了使我的对象与这个 .NET 对象相似,我希望它包含 ParentNode、PreviousSibling、NextSibling 和 ChildNodes 复杂属性。

该表看起来有点像这样,并且可以更改:

  • 编号(整数)
  • 标题(字符串)
  • 描述(字符串)
  • 键(字符串)
  • ParentNodeId (int)
  • OrdinalPosition (int)
  • 只读(布尔)
  • 网址(字符串)

我可能有一些其他属性不需要模拟 .NET SiteMapNode 对象(如 isExternal 布尔值),但我认为这些对这个问题无关紧要。

我当前的映射如下所示:

<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" />

子节点的映射应该只是一个简单的包,它将带回 ParentNodeId 等于当前 ID 的所有 SiteMapNode 对象。我还没有写这个包,但我相信这没什么大不了的。

我似乎无法解决的问题是如何执行 Next/Previous Sibling 属性。该对象可以从每个节点的以下公式派生:

  • PreviousSibling:与当前对象具有相同的ParentNode (ParentNodeId),并且其OrdinalPosition 应该比当前对象的OrdinalPosition 小一。
  • NextSibling:与当前对象具有相同的ParentNode(ParentNodeId),并且其OrdinalPosition应该比当前对象的OrdinalPosition大一。

我认为这可以通过多对一映射的形式属性来实现。这可能吗?我还没有找到一个很好的例子来说明这是如何工作的。

4

2 回答 2

0

我认为您所要求的绝对不可能(尽管如果可以的话,我很想看到解决方案)。会有一个相对简单的解决方法,但 NHibernate 不支持在多端具有索引集合的双向一对多映射。

唯一想到的是有点难看:让父对象为每个子对象保留自己的索引映射(从 OrdinalPosition 键控)。在孩子身上做这样的事情:

public SiteMapNode NextSibling()
{
    return this.Parent.NextSibling(this);
}
于 2009-02-23T22:44:14.823 回答
0

我相信 Stuart 在这种情况下是正确的。对于多对一映射是不可能的。如果 NHibernate 提供了一种在此映射上执行 where 子句的方法,那么我可能有机会。

另一个可能的解决方案虽然效率低,但创建一个使用字段设置器的包。将是 Next/Previous 设置的公共属性仍将返回对象引用(而不是可枚举)。在 getter 中,它只会引用字段中可枚举的第一个位置。延迟加载将是理想的,因为 NHibernate 无法在对象的初始加载中一次性加载该对象。每次访问此对象都会受到惩罚。

我想这两种解决方案都有类似的惩罚。

于 2009-02-25T18:47:22.677 回答