背景
我正在研究遗留的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
答案 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()
查询执行方法完全相同。