1

背景:

我正在处理一个遗留的 DB2 数据库,所以我无法控制模式。我已经在这个网站上搜索了答案,但没有找到。我也搜索了谷歌并没有找到合适的答案。

这里描述的表都使用复合键。我有一个父表存储每个“案例”的资格信息。子表存储与案例相关的每个人的资格信息。子记录由 pin 号区分,以使它们仅在子表中唯一。

我正在使用 NHibernate v3.1 和 Fluent NHibernate v1.2,两者都是通过 NuGet 包获得的。使用 Fluent NHibernate 自动映射器功能映射实体。任何自定义映射都是在每个实体的映射覆盖方法中完成的。

要知道的另一件事是,这些表没有在 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 被 hasmany ofT0265_AG_IN_ELIG及其复合键中不同数量的键列混淆了。通常这种关联是一个依赖关联,其中子实体不是单独映射而是在集合中映射。尝试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 中存在一些问题,即仅在使用 Extra Lazy Loading 时才允许记录绑定。即使这样,从 HQL 不正确地生成 SQL。对此的解决方案是恢复使用 Fluent NHibernate 1.2 和 NHibernate 2.1.2。

下载链接的标题为“Download for NHibernate 2.1.2”。点击下方进入下载页面。

Fluent NHibernate 下载页面

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 回答