変更できないレガシーデータベースがあります。そして、ガベージで遅すぎる古い 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 にマップする方法はありますか?
ありがとう、アレックス