1

他のすべてのテーブルがその主キーの一部を継承する単一の「ベーステーブル」を使用して、ほぼ完全に複合主キーと複合外部キーを使用するかなり大きなDB(〜200テーブル)があります。

  • 親には単一列の主キー ParentId があります
  • 子には複合主キー (ParentId、ChildId) と外部キー ParentId があります
  • Nephew には複合主キー (ParentId、NephewId)、外部キー ParentId および外部キー (ParentId、ChildId) があります。

等々。これまでは、独自の ORM フレームワークでこのシバン全体を管理していましたが、学習するように割り当てられた NHibernate の使用を検討しています (v2.1.2 をダウンロードしました)。

マッピング: 子

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Assembly" namespace="Namespace">
<class name="Child" table="Child">
    <composite-id name="IdChild" class="ChildId">
        <key-many-to-one name="Parent" column="ParentId" class="ParentId"></key-many-to-one>
        <key-property name="Id" column="ChildId" type="Int32"></key-property>
    </composite-id>
    <!--simple properties-->
    <set name="Nephews" table="Nephew">
        <key>
            <column name="ParentId"></column>
            <column name="ChildId"></column>
        </key>
        <one-to-many class="Nephew"/>
    </set>
</class>
</hibernate-mapping> 

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Assembly" namespace="Namespace">
    <class name="Nephew" table="Nephew">
        <composite-id name="IdNephew" class="NephewId">
            <key-many-to-one name="Parent" column="ParentId" class="Parent"></key-many-to-one>
            <key-property name="Id" column="NephewId" type="Int32"></key-property>
        </composite-id>
        <many-to-one name="Child" class="Child">
            <column name="ParentId"></column>
            <column name="ChildId"></column>
        </many-to-one>
        <!--simple properties-->
    </class>

必要に応じて、クラスも投稿できます。簡潔にするために、ここでは省略します (問題がないため、親のマッピングは省略します)。すべてのプロパティは仮想であり、すべてのマッピング ファイルは埋め込みリソースであり、すべての複合 ID には、Equals と GetHashCode をオーバーライドする独自のクラスがあります。

問題は、単純に初期化new Nephew()され、に渡された Nephew のインスタンスを保存できない_session.Save()ことSystem.IndexOutOfRangeException: Invalid index n for this SqlParameterCollection with Count=n.です。

マッピングで重複する唯一の列はParentId. のマッピング、およびすべての関連プロパティのmany-to-oneマッピングを削除すると、すべて正常に機能します。NephewsetChild

この例外を報告するいくつかの投稿を見つけました。私の場合、最も適切なのはthis oneのようです。これにより、現在のスキーマは NHibernate では実行不可能であるという直感が得られます。私が間違っていると教えてください:-)

ノート:

  • 私は現在 Fluent を使用していませんが、それはオプションかもしれませんが、最初に基本を学ぶことを好みました。
  • はい、複合主キーが厄介な問題であることは認識しています。この DB は何年にもわたって数人の手を経てきましたが、おそらくそれほど熟練した人ではありませんが、リファクタリングする前に 10 000 に数えます
4

2 に答える 2

0

残念ながら、推測したように、その関係を現在の形式でマップすることはできません。

ただし、回避策があります。Nephew.Child多対1としてマッピングする代わりにChildId、通常のプロパティとしてマッピングし、子を取得する必要がある場合はクエリを使用します。

ハッキングのチャンスがもう1つあります。Nephew.Childがnullでなく、変更できない場合にのみ、親の代わりに子を参照するキーをマップできます。

<class name="Nephew" table="Nephew">
  <composite-id name="IdNephew" class="NephewId">
    <key-many-to-one name="Child">
      <column="ParentId">
      <column="ChildId">
    </key-many-to-one>
    <key-property name="Id" column="NephewId"/>
  </composite-id>
</class>
于 2010-10-08T17:20:08.467 に答える
0

私はより良い解決策を見つけました:

<many-to-one name="Child" class="Child">
    <formula>ParentId</formula>
    <column name="ChildId"></column>
</many-to-one>

私はすでにそれを試しましたが、エラーが発生しましたが、このパッチに気づいたので、3.0.0 alpha2 をダウンロードすると、すべて正常に動作しました! このソリューションのおかげで、Nephew.Child意図したとおりにプロパティをマッピングできます。

ただし、まだメソッドが必要Child.Add(Nephew)です(ただし、ドキュメントでも推奨されていることに気付きました)

于 2010-10-13T07:22:50.703 に答える