Как смоделировать отношения, которые NHibernate (или Hibernate) не поддерживает - PullRequest
2 голосов
/ 26 марта 2010

У меня есть ситуация, в которой идеальные отношения, я полагаю, связаны с наследованием объекта значения. К сожалению, это не поддерживается в NHibernate, поэтому любое решение, которое я придумаю, будет менее чем идеальным.

Допустим, что:

  • Объекты «Элемент» имеют «Местоположение», которое может иметь один из нескольких различных форматов.
  • Эти форматы совершенно разные, без перекрывающихся полей.
  • Мы будем иметь дело с каждым местоположением в формате, указанном в данных, без попыток преобразования из одного формата в другой.
  • Каждый предмет имеет ровно одну локацию.
  • «SpecialItem» является подтипом Item, однако, он уникален тем, что имеет ровно два местоположения.
  • Агрегированные объекты «Группа».
  • «LocationGroup» является подтипом группы.
  • LocationGroup также имеет одно Местоположение, которое может быть в любом из форматов, как описано выше.
  • Хотя меня интересуют Предметы по группам, меня также интересует возможность найти все предметы с одинаковым Местоположением, независимо от того, в какую группу они входят.

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

Диаграмма дилеммы картографии http://www.freeimagehosting.net/uploads/592ad48b1a.jpg

Анализируя вышеизложенное, я делаю следующие наблюдения:

  • Я трактую Локации полиморфно, имея в виду супертип, а не подтип.
  • По логике, местоположения должны быть «объектами значения», а не сущностями, поскольку бессмысленно проводить различие между двумя объектами местоположения, которые имеют все одинаковые значения. Таким образом, равенство между местоположениями должно основываться на сравнении полей, а не на идентификаторах. Кроме того, объекты-значения должны быть неизменяемыми, а общие ссылки не допускаются.
  • Используя NHibernate (или Hibernate), обычно можно отобразить объекты-значения с помощью ключевого слова «component», что приведет к тому, что поля класса будут отображены непосредственно в таблицу базы данных, которая представляет содержащий класс. Другими словами, в базе данных не будет отдельной таблицы «Locations» (и, следовательно, у Locations не будет идентификаторов).
  • NHibernate (или Hibernate) в настоящее время не поддерживает наследование для объектов-значений.

Мой выбор, который я вижу:

  1. Игнорировать тот факт, что Locations должны быть объектами-значениями, и отображать их как сущности. Это позволит решить проблемы с отображением наследования, поскольку NHibernate поддерживает наследование сущностей. Недостатком является то, что мне приходится сталкиваться с проблемами сглаживания. (Это означает, что если несколько объектов имеют ссылку на одно и то же местоположение, то изменение значений для местоположения одного объекта приведет к изменению местоположения для других объектов, которые имеют ссылку на одну и ту же запись местоположения.) Я хочу по возможности этого избежать. Другим недостатком является то, что объекты обычно сравниваются по их идентификаторам. Это будет означать, что два объекта Location будут считаться не равными, даже если значения всех их полей одинаковы. Это было бы недопустимо и недопустимо с точки зрения бизнеса.
  2. Распределение Locations в один класс, чтобы больше не существовало отношений наследования для Locations. Это позволило бы обрабатывать Locations как объекты-значения, которые могут быть легко обработаны с помощью « компонент »в NHibernate. Недостатком в этом случае будет то, что модель предметной области становится более слабой, более хрупкой и менее обслуживаемой.
  3. Сделайте некоторое «творческое» отображение вфайлы hbm для того, чтобы принудительно отобразить поля Location в таблицы содержащих сущностей без использования ключевого слова component. Этот подход описан Колином Джеком здесь . Моя ситуация более сложная, чем та, которую он описывает, из-за того, что у SpecialItem есть второе Location, и из-за того, что у другого объекта, LocationGroup, также есть Locations. Я мог бы заставить его работать, но сопоставления были бы не интуитивно понятными и поэтому трудными для понимания и поддержки другими разработчиками в будущем. Кроме того, я подозреваю, что при использовании Fluent NHibernate эти сложные сопоставления, скорее всего, будут невозможны, поэтому я воспользуюсь преимуществами использования этого инструмента, по крайней мере, в такой ситуации.

Конечно, другие сталкивались с подобными ситуациями. Я надеюсь, что кто-то, кто «был там, сделал это», может поделиться какой-то мудростью. :-)

Так вот в чем вопрос ... Какой подход следует предпочитать в этой ситуации? Зачем? Есть ли лучший вариант, который я не рассмотрел?

1 Ответ

1 голос
/ 26 марта 2010

Всего несколько замечаний / вопросов ...

  • если разные форматы местоположения не имеют перекрывающихся полей, какова их общая черта, которая сделает их кандидатами на иерархию подкласса? Вы действительно можете определить общий интерфейс для базового класса Location?
  • это TypeALocation сравнимо с TypeBLocation?
  • это два местоположения в SpecialItem одного типа, или они могут быть смешаны?
  • Может ли элемент изменить свое местоположение на другой тип времени выполнения?

Как вы заявили выше, объекты-значения не могут быть полиморфными. Исходя из того, что вы описываете, я не понимаю, как вы можете полиморфически относиться к локациям.

Обновление Если вы не можете определить общий базовый интерфейс для ваших типов местоположений, очень неловко пытаться обрабатывать их полиморфно, независимо от того, есть ORM или нет, Используя приведенный ниже пример, даже для доступа к любой информации о реальном местоположении, в котором я живу, вам нужно было уменьшить его до адреса улицы или координаты широты / долготы. Полиморфизм предназначен именно для того, чтобы избежать необходимости таких понижений (и включает поля типа и т. Д.)!

Рассматривая варианты, которые вы описали выше, с учетом всего этого:

  1. Так же, как и вам, мне это тоже не нравится (вряд ли удивительно).
  2. Может быть приемлемым вариантом, если не так много типов местоположений, и вы можете быть достаточно уверены, что реализовали все когда-либо необходимые типы. В этом случае класс предметной области будет практически аналогом C-союза с полем типа. Это немного неловко в использовании, но полиморфная попытка была бы еще более неловкой ИМХО.
  3. Это определенно интересная идея, с которой я, вероятно, когда-нибудь поэкспериментирую в проекте для домашних животных, но я не совсем уверен, что мне хотелось бы использовать такие приемы в моем производственном коде. Я предполагаю, что это также может быть сделано с пользовательским типом отображения, который сопоставит ваш компонент с определенным подклассом. Но опять же, мы снова пытаемся вписать эти несовместимые типы в иерархию типов ... единственная веская причина попробовать этот путь, если есть много типов местоположений и / или в будущем могут появиться новые типы.
...