Свободный NHibernate не отображает дочерние строки в свойство коллекции (база данных DB2) - PullRequest
1 голос
/ 04 ноября 2011

Справочная информация:

Я работаю над устаревшей базой данных DB2, поэтому не могу управлять схемой. Я искал ответы на этом сайте и не нашел ни одного. Я также искал в Google и не нашел подходящего ответа.

В описанных здесь таблицах используются составные ключи. У меня есть родительская таблица, в которой хранится информация о приемлемости для каждого «случая». Дочерняя таблица хранит информацию о праве на участие, касающуюся каждого лица, связанного с делом. Дочерние записи различаются по номеру пин-кода, чтобы сделать их уникальными только в дочерней таблице.

Я использую 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

Ответы [ 2 ]

0 голосов
/ 15 ноября 2011

Я смог понять это.По сути, существует некоторая проблема в NHibernate 3.1, которая позволяет привязывать записи только при использовании Extra Lazy Loading.Даже тогда SQL неправильно генерируется из HQL.Решением этой проблемы было вернуться к использованию Fluent NHibernate 1.2 с NHibernate 2.1.2.

Ссылка для загрузки называется «Загрузить для NHibernate 2.1.2».Нажмите ниже, чтобы перейти на страницу загрузок.

Свободная страница загрузок 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()

Основные отличия в файле сопоставления заключаются в том, что мы не используем обратное, и мы возвращаем «GenericPersistentBag» из NHibernate.

Метод выполнения запроса:

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()

Метод выполнения запроса идентичен.

0 голосов
/ 08 ноября 2011

Я публикую ответ, потому что его гораздо легче читать и редактировать.

Мое следующее предположение состоит в том, что 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));
})
...