Работа с большими иерархиями наследования классов в NHibernate - PullRequest
2 голосов
/ 02 августа 2011

Моя модель выглядит следующим образом:

  • InsurancePolicy
    • VehicleInsurancePolicy
      • AbcInsurancePolicy
      • DefInsurancePolicy
    • Домашняя страховкаПолиция
      • GhiInsurancePolicy
      • PqrInsurancePolicy
    • SomeOtherInsurancePolicy
      • ... etc

где InsurancePolicy - это абстрактный класс, который является базовым классом для всех конкретных реализаций страховых полисов.AbcInsurancePolicy, DefInsurancePolicy и т. Д. Являются реализациями, которые соответствуют определенным страховым продуктам.Иногда я определяю другие абстрактные классы для подгрупп политик с подмножеством общих полей (например, VehicleInsurancePolicy).

Я сопоставил эти классы, используя стратегию «Таблица на подкласс, используя дискриминатор».Таблица InsurancePolicy содержит около 60 полей, и каждая объединенная таблица добавляет от 10 до 30 полей.Я использовал эту стратегию, потому что:

  • У меня много подклассов с большим количеством полей.Стратегия таблица-на-класс-иерархия закончилась бы наличием одной таблицы с большим количеством пустых столбцов.
  • Я хочу иметь возможность расширять приложение, добавляя другие подклассы, не изменяя схему таблицы InsurancePolicy.

InsurancePolicy часто используется как отношение «многие-к-одному» в других объектах, таких как «Оплата», «Документ» и т. Д.

NHibernate генерирует много левых внешних соединений при запросах к InsurancePolicy.потому что он не знает тип.Это очень неэффективно, так как мне нужно присоединиться ко многим столам.Проблема становится еще хуже, когда лениво загружаются свойства многие-к-одному, содержащие InsurancePolicy, потому что он довольно часто используется в моей модели.Конкретные реализации используются редко, только в сценариях редактирования / подробностей, где указывается фактический тип и объединяются только необходимые таблицы.

Тогда я использовал комбинацию дискриминатор + соединение.Таким образом, таблица InsurancePolicy содержит информацию о типе.К сожалению, отображение "join" не поддерживает отложенную загрузку.Я попытался установить fetch = "select", однако они генерируют N + 1 выбор при запросе нескольких страховых полисов.

// select from 1 table, "join" class must be lazy-loaded on access
Session.Get<InsurancePolicy>(5) 

// select includes a join, since we explicitly specified a concrete type
Session.Get<SomeConcreteInsurancePolicy>(5)

Итак, мои вопросы:

  1. Есть ли способ расширить NHibernate, чтобы он работал, как описано выше?
  2. Есть ли другой способ сопоставления этихбольшие / сложные иерархии классов?

1 Ответ

2 голосов
/ 02 августа 2011

На основании этого:

Конкретные реализации используются редко, только в сценариях редактирования / подробностей

Я рекомендую разбить InsurancePolicy на две части:

  • InsurancePolicy, содержащая только свойства из текущего базового класса
  • PolicyDetails, абстрактный базовый класс для иерархии.

Между этими двумя классами существует взаимно-однозначное отношение.

Прелесть этого в том, что вам не нужно ничего менять (кроме незначительного изменения в представлениях редактирования политики, чтобы указать им новые отношения)

...