1

バックグラウンド:

私はレガシーDB2データベースで作業しているので、スキーマを制御できません。このサイトで回答を検索しましたが、見つかりませんでした。私もグーグルを検索しましたが、適切な答えが見つかりませんでした。

ここで説明する表は両方とも複合キーを利用しています。「ケース」ごとの適格性情報を格納する親テーブルがあります。子テーブルには、ケースに関連付けられている各個人に関する適格性情報が格納されます。子レコードはピン番号で区別され、子テーブルでのみ一意になります。

NHibernatev3.1とFluentNHibernatev1.2を使用していますが、どちらもNuGetパッケージを介して取得しています。エンティティは、FluentNHibernate自動マッパー機能を使用してマッピングされます。カスタムマッピングは、各エンティティのマッピングオーバーライドメソッドで実行されます。

もう1つ知っておくべきことは、これらのテーブルにはDB2で定義された「主キー」がないということです。それらには「一意のキー」しかありません。これは、以下の複合キーの定義に表示されます(コードを参照)。

T0026_AG_ELIGは、親テーブルと対応するPOCOクラスの名前です。
T0265_AG_IN_ELIGは、子テーブルと対応するPOCOクラスの名前です。

問題:

問題は、クエリを実行すると、すべてのデータがクエリされ、親レコードがクラスに正常にマップされますが、返された子行が親クラスのコレクションにマップされないことです。NHibernateは、親データと子データのクエリを生成します。データベースに対して独自のクエリを実行すると、条件の正しいデータが返されます。何らかの理由で、子レコードが親(T0026)クラスのプロパティにバインドされていないだけです。

質問:

T0265_AG_IN_ELIGから戻ってくる複数の行を取得して、対応するクラスにマップし、親クラス(T0026_AG_ELIG)の指定されたコレクションプロパティに適切にロードするには、何をする必要がありますか?

親のコレクションプロパティ(T0026_AG_ELIG):

Public Overridable Property IndividualEligibilityRecords As IList(Of T0265_AG_IN_ELIG)

親のマッピングオーバーライド(T0026_AG_ELIG):

mapping.CompositeId() _
   .KeyProperty(Function(x) x.CASE_NUM) _
   .KeyProperty(Function(x) x.PROGRAM_CD) _
   .KeyProperty(Function(x) x.SUBPROGRAM_CD) _
   .KeyProperty(Function(x) x.AG_SEQ_NUM) _
   .KeyProperty(Function(x) x.CAG_ELIG_SEQ_NUM)

mapping.HasMany(Of T0265_AG_IN_ELIG)(Function(x) x.IndividualEligibilityRecords) _
   .Cascade.All() _
   .Inverse() _
   .Fetch.Join() _
   .KeyColumns.Add("CASE_NUM") _
   .KeyColumns.Add("PROGRAM_CD") _
   .KeyColumns.Add("SUBPROGRAM_CD") _
   .KeyColumns.Add("AG_SEQ_NUM") _
   .KeyColumns.Add("CAG_ELIG_SEQ_NUM") _
   .Not.LazyLoad() _
   .AsList(Function(x) x.Column("PIN_NUM"))


   mapping.IgnoreProperty(Function(x) x.IndividualEligibilityRecords)

子のマッピングオーバーライド(T0265_AG_IN_ELIG):

mapping.CompositeId() _
   .KeyProperty(Function(x) x.CASE_NUM) _
   .KeyProperty(Function(x) x.PROGRAM_CD) _
   .KeyProperty(Function(x) x.SUBPROGRAM_CD) _
   .KeyProperty(Function(x) x.AG_SEQ_NUM) _
   .KeyProperty(Function(x) x.CAG_ELIG_SEQ_NUM) _
   .KeyProperty(Function(x) x.PIN_NUM)

次のコードが実行され、クエリが実行されます。

transaction = session.BeginTransaction()

query = session.CreateQuery("FROM T0026_AG_ELIG AS T0026 " _
      & "WHERE T0026.CASE_NUM = :p0 AND T0026.PROGRAM_CD = :p1 AND " _
      & "SUBPROGRAM_CD = :p2 AND AG_SEQ_NUM = :p3 AND CAG_ELIG_SEQ_NUM = :p4")

query.SetParameter("p0", caseNumber)
query.SetParameter("p1", programCode)
query.SetParameter("p2", subProgramCode)
query.SetParameter("p3", agSequenceNumber)
query.SetParameter("p4", cagEligSequenceNumber)

result = query.List()
transaction.Commit()

If result.Count = 1 Then
   Return DirectCast(result.Item(0), T0026_AG_ELIG)
End If
4

2 に答える 2

0

読みやすく編集しやすいので、回答を投稿します。

私の次の推測は、NHは、hasmanyofT0265_AG_IN_ELIGとそのcompositekeyのキー列の数が異なることで混乱しているということです。通常、この種の関連付けは、子エンティティが個別にマッピングされるのではなく、コレクション内にマッピングされる依存関連付けです。自動マッピングから除外T0265_AG_IN_ELIGして、次のようにマッピングしてみてくださいT0026_AG_ELIG

mapping.HasMany(Of T0265_AG_IN_ELIG)(Function(x) x.IndividualEligibilityRecords) _
   .Cascade.All() _
   .Inverse() _
   .KeyColumns.Add("CASE_NUM", "PROGRAM_CD", "SUBPROGRAM_CD", "AG_SEQ_NUM", "CAG_ELIG_SEQ_NUM") _
   .Not.LazyLoad() _
   .AsList(Function(x) x.Column("PIN_NUM"))
   .Component(Function(c) c.ParentReference(Function(x) x.T0026_AG_ELIG))

アップデート:

の価値は何ですか:

DirectCast(result.Item(0), T0026_AG_ELIG).IndividualEligibilityRecords.GetType().Name

更新:T0265_AG_IN_ELIGを自動マッピングから除外した場合は、コンポーネント内のすべての列を指定する必要があります。

class AutomapConfiguration : DefaultAutomappingConfiguration
{
    public override bool ShouldMap(Type type)
    {
        return type != typeof(T0265_AG_IN_ELIG);
    }
}

class T0265_AG_IN_ELIG
{
    public T0026_AG_ELIG T0026_AG_ELIG { get; set; }
    public string Prop1 { get; set; }
    public string Prop2 { get; set; }
    public string Prop3 { get; set; }
}


.Component(c =>
{
    c.ParentReference(x => x.T0026_AG_ELIG);
    c.Map(x => x.Prop1));
    c.Map(x => x.Prop2));
    c.Map(x => x.Prop3));
})
于 2011-11-08T08:27:22.057 に答える
0

私はこれを理解することができました。基本的に、NHibernate 3.1には、ExtraLazyLoadingを使用している場合にのみレコードをバインドできるという問題があります。それでも、SQLはHQLから不適切に生成されます。これに対する解決策は、FluentNHibernate1.2とNHibernate2.1.2の使用に戻すことでした。

ダウンロードのリンクのタイトルは「DownloadforNHibernate2.1.2」です。ダウンロードページに移動するには、以下をクリックしてください。

FluentNHibernateダウンロードページ

T0026のマッピングオーバーライド:

mapping.CompositeId() _
   .KeyProperty(Function(x) x.CASE_NUM) _
   .KeyProperty(Function(x) x.PROGRAM_CD) _
   .KeyProperty(Function(x) x.SUBPROGRAM_CD) _
   .KeyProperty(Function(x) x.AG_SEQ_NUM) _
   .KeyProperty(Function(x) x.CAG_ELIG_SEQ_NUM) _

mapping.HasMany(Of T0265_AG_IN_ELIG)(Function(x) x.IndividualEligibilityRecords) _
   .KeyColumns.Add("CASE_NUM", "PROGRAM_CD", "SUBPROGRAM_CD", "AG_SEQ_NUM", "CAG_ELIG_SEQ_NUM") _
   .Cascade.All() _
   .Table("PWS639TC.T0265_AG_IN_ELIG") _
   .Not.LazyLoad() _
   .AsBag()

マッピングファイルの主な違いは、インバースを使用しておらず、NHibernateから「GenericPersistentBag」を返すことです。

クエリ実行方法:

transaction = session.BeginTransaction()

query = session.CreateQuery("FROM T0026_AG_ELIG AS T0026 " _
              & "WHERE T0026.CASE_NUM = :p0 " _
              & "AND T0026.PROGRAM_CD = :p1 " _
              & "AND SUBPROGRAM_CD = :p2 " _
              & "AND AG_SEQ_NUM = :p3 " _
              & "AND CAG_ELIG_SEQ_NUM = :p4")

query.SetParameter("p0", caseNumber)
query.SetParameter("p1", programCode)
query.SetParameter("p2", subProgramCode)
query.SetParameter("p3", agSequenceNumber)
query.SetParameter("p4", cagEligSequenceNumber)

result = query.List()

If result.Count = 1 Then
   returnable = DirectCast(result.Item(0), T0026_AG_ELIG)
End If

transaction.Commit()

クエリの実行方法は同じです。

于 2011-11-14T20:50:22.413 に答える