Background:
I am working on a legacy DB2 database, so I have no control over the schema. I have searched this site for answers and have found none. I have also searched google and not found a suitable answer.
The tables described herein both utilize composite keys. I have a parent table that stores eligibility information per “case”. The child table stores eligibility information regarding each individual associated with the case. The child records are differentiated by pin number to make them unique in the child table only.
I am using NHibernate v3.1 with Fluent NHibernate v1.2, both acquired via NuGet packages. The entities are mapped in using the Fluent NHibernate auto-mapper functionality. Any custom mapping is done in the mapping override method for each entity.
Another thing to know is that these tables do not have a “primary key” defined in DB2. They only have “unique keys”, which are what you see in the composite key definition below (see code).
T0026_AG_ELIG is the name of the parent table and the corresponding POCO class.
T0265_AG_IN_ELIG is the name of the child table and the corresponding POCO class.
Problem:
The problem is that when I execute the query, all the data is queried, the parent record is successfully mapped to the class, but the returned child rows do not map into the collection on the parent class. NHibernate does generate the queries for the parent and child data. When I execute my own query against the database, the correct data for the conditions does come back. For some reason, the child records are just not being bound to the property on the parent (T0026) class.
Question:
What do I need to do to get the multiple rows coming back from T0265_AG_IN_ELIG to map to their corresponding class and load properly into the specified collection property on the parent class (T0026_AG_ELIG)?
Collection Property of Parent (T0026_AG_ELIG):
Public Overridable Property IndividualEligibilityRecords As IList(Of T0265_AG_IN_ELIG)
Mapping Override for Parent (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)
Mapping Override for Child (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)
The following code executes to execute the query:
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
I post in an answer because its much easier to read and edit.
My next guess is that NH is confused by the different number of key columns in the hasmany of
T0265_AG_IN_ELIGand its compositekey. normally this kind of association is a dependent association where the child-entities are not mapped seperatly but within the collection. Try excludeT0265_AG_IN_ELIGfrom automapping and mapping it like this inT0026_AG_ELIGUpdate:
What is the value of:
Update: of yourse when you have excluded T0265_AG_IN_ELIG from automapping you have to specify all columns in the component