0

nHibernate を使用して、.NET の System.Web.SiteMapNode に非常によく似たオブジェクトをマップしています。オブジェクトをこの .NET オブジェクトに似たものにするために、ParentNode、PreviousSibling、NextSibling、および ChildNodes の複合プロパティを含めたいと考えています。

表は次のように見えますが、変更可能です。

  • ID (整数)
  • タイトル(文字列)
  • 説明 (文字列)
  • キー (文字列)
  • ParentNodeId (整数)
  • OrdinalPosition (整数)
  • 読み取り専用 (ブール値)
  • 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 マッピングは単純な多対 1 マッピングであるため、簡単です。これは私が持っているコードです(テストされていませんが、正しいと思います):

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

子ノードのマッピングは、現在の ID と等しい ParentNodeId を持つすべての SiteMapNode オブジェクトを戻す単純なバッグにする必要があります。このバッグについてはまだ書いていませんが、それほど大したことではないと思います。

解決できないように見える問題は、次/前の兄弟プロパティを実行する方法です。このオブジェクトは、各ノードの次の式から導出できます。

  • PreviousSibling: 現在のオブジェクトと同じ ParentNode (ParentNodeId) を持ち、その OrdinalPosition は現在のオブジェクトの OrdinalPosition よりも 1 小さい必要があります。
  • NextSibling: 現在のオブジェクトと同じ ParentNode (ParentNodeId) を持ち、その OrdinalPosition は現在のオブジェクトの OrdinalPosition より 1 大きい必要があります。

これは、多対 1 マッピングの正式な属性によって実現できると思います。これは可能ですか?これがどのように機能するかの良い例は見つかりませんでした。

4

2 に答える 2

0

私はあなたが求めていることが厳密に可能であるとは思いません(それがあれば解決策を見ることに非常に興味がありますが)。比較的簡単な回避策がありますが、NHibernateは、多端にインデックス付きコレクションを使用した双方向の1対多マッピングをサポートしていません。

頭に浮かぶのは少し醜いことだけです。親オブジェクトに、各子オブジェクトへの独自のインデックスマップ(OrdinalPositionからキーオフ)を保持させることです。子供に次のようなことをします:

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

この状況ではスチュアートは正しいと思います。多対1のマッピングを行うことは不可能です。NHibernateが、このマッピングの条項を実行する方法を提供した場合、私はチャンスがあるかもしれません。

非効率的ですが、別の可能な解決策は、フィールドセッターを使用するバッグを作成することです。Next / Previous設定になるパブリックプロパティは、(列挙可能ではなく)オブジェクト参照を返します。ゲッターでは、フィールド内の列挙可能なものの最初の位置を参照するだけです。NHibernateは、オブジェクトの初期ロードでは1回の取得でこのオブジェクトをロードできないため、遅延ロードが理想的です。毎回このオブジェクトにアクセスするとペナルティが発生します。

どちらのソリューションにも同様のペナルティがあると思います。

于 2009-02-25T18:47:22.677 に答える