6

変更できないレガシーデータベースがあります。そして、ガベージで遅すぎる古い DataAccess 層の代わりに NHibernate に移行しようとしています。

次のようなテーブルがあります。

GPI テーブルには (PU_ID, PAR_ID, Data, Data2) 列があります
BLOCK テーブルには (GA_ID, Data, PAR_ID) 列があります
COMPANY テーブルには (PU_ID, Data) 列があります

上記のテーブルに対してこれらのマッピングを作成しました。

GPI

<class name="GroupPartnerInterest" table="[GPI]">
    <composite-id >
        <key-property name="GroupId" column="PAR_ID" />
        <key-property name="CompanyId" column="PU_ID" />
    </composite-id>
    <property name="data" column="Data"/>
    <property name="data2" column="Data2"/>
    <many-to-one name="Company" fetch="select" cascade="none">
        <column name="PU_ID"/>
    </many-to-one>
    <set name="Blocks" cascade="none" inverse="true" fetch="select">
        <key property-ref="GroupId">
            <column name="PAR_ID"/>
        </key>
        <one-to-many class="Block"/>
    </set>
</class>

ブロック

<class name="Block" table="[BLOCK]" >
    <id name="BlockId" column="GA_ID" >
        <generator class="assigned"/>
    </id>
    <property name="data" column="Data"/>
    <property name="GroupId" column="PAR_ID"/>
    <set name="GroupPartnerInterests" cascade="all-delete-orphan" fetch="select">
        <key property-ref="GroupId">
            <column name="PAR_ID"/>
        </key>
        <one-to-many class="GroupPartnerInterest"/>
    </set>
</class>

会社

<class name="Company" table="[COMPANY]">
    <id name="CompanyId" column="PU_ID">
        <generator class="assigned"/>
    </id>
    <property name="data" column="Data"/>
    <set name="GroupPartnerInterests" cascade="none" inverse="true" fetch="select">
        <key>
            <column name="PU_ID"/>
        </key>
        <one-to-many class="GroupPartnerInterest"/>
    </set>
</class>

クラスはとてもシンプルでわかりやすいです。すべてが Equals および GetHashCode メソッドを実装しています。

動作するナビゲーターのリストは次のとおりです。

  • GroupPartnerInterest.Company - 素晴らしい作品
  • Company.GroupPartnerInterests - 素晴らしい作品
  • GroupPartnerInterest.Company - 素晴らしい作品

そして、これら2つは失敗します:

  • Block.GroupPartnerInterests:

私は単体テストを持っています:

[TestMethod]
public void TestGroupPartnerInterests()
{
    using ( ISession session = SessionFactory.OpenSession() )
    {
        IList<Block> blocks = session.CreateCriteria( typeof( Block ) )
            .SetMaxResults( 5 ).List<Block>();

        foreach ( var block in blocks )
        {
            TestContext.WriteLine( "Block #{0}", block.BlockId );

            if ( block.GroupPartnerInterests != null )
            {
                foreach ( GroupPartnerInterest gpi in block.GroupPartnerInterests )
                {
                    TestContext.WriteLine( "Company '{0}':", gpi.Company.CompanyId );
                }
            }
        }
    }
}

GPI マッピング テストでブロック ナビゲーション マッピングをコメントアウトすると、動作し、いくつかのデータが出力されます。

Block #1
Company 'LALA':
Company 'LALA SA': Company 'BG PO': Company 'LIMPOPO': Company 'HAHA': Company 'Other partner(s)': Block #4







しかし、テストは次のエラーで失敗します。

NHibernate.LazyInitializationException: Initializing[Model.EntityClasses.Block#999] - ロールのコレクションの遅延初期化に失敗しました: Model.EntityClasses.Block.GroupPartnerInterests、セッションまたはセッションが閉じられませんでした。

「999」は既存の PAR_ID です。データは一貫しています。この PAR_ID を持つ 2 つのブロックと、GPI にいくつかのレコードがあります。

ある時点でセッションを閉じるのはなぜですか?

  • GroupPartnerInterest.Blocks:

単体テストは上で述べたものとほぼ同じで、異なるプロパティが使用されているだけです。エラーは次のとおりです。

NHibernate.MappingException: NHibernate.MappingException: プロパティが見つかりません: エンティティ Model.EntityClasses.GroupPartnerInterest の GroupId。

GPI マッピングの Blocks navigator の要素から "property-ref=GroupId" を削除すると、次の例外が発生します。

NHibernate.FKUnmatchingColumnsException: NHibernate.FKUnmatchingColumnsException: 外部キー (FKA3966498349694F:[BLOCK] [PAR_ID])) には、参照される主キー ([GPI] [PAR_ID, PU_ID]) と同じ数の列が必要です。

GroupPartnerInterest.Blocks ナビゲーターが機能するように、ブロックを GPI にマップする方法はありますか?

ありがとう、アレックス

4

1 に答える 1

2

問題は次のとおりです。

  • 複合 ID を持つエンティティがある場合、それへのすべての参照は複合 ID を維持する必要があるため、2 つの外部キーが必要です。
  • Blocks inGroupPartnerInterestは集合なので、外部キーは in にありBlocks、 を指していGroupPartnerInterestます。利用できない 2 つの外部キーが必要になります。
  • property-ref主キーを他のプロパティに置き換えることです。したがって、関係の一方の側にあるテーブルのプロパティである ですがGroupPartnerInterest、 はありませんGroupId
  • おそらくfor を使用できます(2 つの外部キーが欠落しているため、 を指摘するため) が、私はそれについてよく考えます。property-refGroupPartnerInterest.BlocksBlock.PAR_IDGPI.PAR_ID

ここで実用的なソリューションを提供することはできません。私は複合キーを使用していませんが、これはより複雑です。しかし、さらにいくつかの考えがあります:

  • 複合キーを避けようとします。それが不可能な場合は、複合キーを表すクラスを記述します。これにより、取り扱いがはるかに簡単になります。
  • 主キーに基づいていない関係を避けようとします。そうしない理由があるかもしれませんが、NHはそれらをサポートしています。

セッションが閉じられているのはなぜですか? わかりません。スタックトレースを見てみましょう。using ブロック内から本当に例外がスローされたのでしょうか。それともTestCleanupメソッドからスローされますか?

于 2010-08-26T06:52:59.150 に答える