Fluent NHibernate没有将子行映射到集合属性(DB2数据库)

时间:2011-11-04 16:33:13

标签: vb.net nhibernate orm fluent-nhibernate fluent-nhibernate-mapping

背景

我正在研究遗留的DB2数据库,所以我无法控制架构。我搜索了这个网站的答案,但没有找到。我也搜索了谷歌,但没有找到合适的答案。

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

我正在使用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)上的指定collection属性中,我需要做什么?

父母的收藏属性(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

2 个答案:

答案 0 :(得分:0)

我在答案中发帖,因为它更容易阅读和编辑。

我的下一个猜测是NH被T0265_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));
})

答案 1 :(得分:0)

我能够弄清楚这一点。从本质上讲,NHibernate 3.1中存在一些问题,它只会在使用Extra Lazy Loading时让记录绑定。即使这样,SQL也是从HQL中不正确地生成的。对此的解决方案是恢复使用Fluent NHibernate 1.2和NHibernate 2.1.2。

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

Fluent NHibernate Downloads Page

映射替代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()

查询执行方法完全相同。