У меня есть ситуация, в которой идеальные отношения, я полагаю, связаны с наследованием объекта значения. К сожалению, это не поддерживается в NHibernate, поэтому любое решение, которое я придумаю, будет менее чем идеальным.
Допустим, что:
- Объекты «Элемент» имеют «Местоположение», которое может иметь один из нескольких различных форматов.
- Эти форматы совершенно разные, без перекрывающихся полей.
- Мы будем иметь дело с каждым местоположением в формате, указанном в данных, без попыток преобразования из одного формата в другой.
- Каждый предмет имеет ровно одну локацию.
- «SpecialItem» является подтипом Item, однако, он уникален тем, что имеет ровно два местоположения.
- Агрегированные объекты «Группа».
- «LocationGroup» является подтипом группы.
- LocationGroup также имеет одно Местоположение, которое может быть в любом из форматов, как описано выше.
- Хотя меня интересуют Предметы по группам, меня также интересует возможность найти все предметы с одинаковым Местоположением, независимо от того, в какую группу они входят.
Я прошу прощения за количество перечисленных выше условий, но боюсь, что дальнейшее его упрощение не будет реально отражать трудности ситуации. Вот как можно изобразить вышесказанное:
Диаграмма дилеммы картографии http://www.freeimagehosting.net/uploads/592ad48b1a.jpg
Анализируя вышеизложенное, я делаю следующие наблюдения:
- Я трактую Локации полиморфно, имея в виду супертип, а не подтип.
- По логике, местоположения должны быть «объектами значения», а не сущностями, поскольку бессмысленно проводить различие между двумя объектами местоположения, которые имеют все одинаковые значения. Таким образом, равенство между местоположениями должно основываться на сравнении полей, а не на идентификаторах. Кроме того, объекты-значения должны быть неизменяемыми, а общие ссылки не допускаются.
- Используя NHibernate (или Hibernate), обычно можно отобразить объекты-значения с помощью ключевого слова «component», что приведет к тому, что поля класса будут отображены непосредственно в таблицу базы данных, которая представляет содержащий класс. Другими словами, в базе данных не будет отдельной таблицы «Locations» (и, следовательно, у Locations не будет идентификаторов).
- NHibernate (или Hibernate) в настоящее время не поддерживает наследование для объектов-значений.
Мой выбор, который я вижу:
- Игнорировать тот факт, что Locations должны быть объектами-значениями, и отображать их как сущности. Это позволит решить проблемы с отображением наследования, поскольку NHibernate поддерживает наследование сущностей. Недостатком является то, что мне приходится сталкиваться с проблемами сглаживания. (Это означает, что если несколько объектов имеют ссылку на одно и то же местоположение, то изменение значений для местоположения одного объекта приведет к изменению местоположения для других объектов, которые имеют ссылку на одну и ту же запись местоположения.) Я хочу по возможности этого избежать. Другим недостатком является то, что объекты обычно сравниваются по их идентификаторам. Это будет означать, что два объекта Location будут считаться не равными, даже если значения всех их полей одинаковы. Это было бы недопустимо и недопустимо с точки зрения бизнеса.
- Распределение Locations в один класс, чтобы больше не существовало отношений наследования для Locations. Это позволило бы обрабатывать Locations как объекты-значения, которые могут быть легко обработаны с помощью « компонент »в NHibernate. Недостатком в этом случае будет то, что модель предметной области становится более слабой, более хрупкой и менее обслуживаемой.
- Сделайте некоторое «творческое» отображение вфайлы hbm для того, чтобы принудительно отобразить поля Location в таблицы содержащих сущностей без использования ключевого слова component. Этот подход описан Колином Джеком здесь . Моя ситуация более сложная, чем та, которую он описывает, из-за того, что у SpecialItem есть второе Location, и из-за того, что у другого объекта, LocationGroup, также есть Locations. Я мог бы заставить его работать, но сопоставления были бы не интуитивно понятными и поэтому трудными для понимания и поддержки другими разработчиками в будущем. Кроме того, я подозреваю, что при использовании Fluent NHibernate эти сложные сопоставления, скорее всего, будут невозможны, поэтому я воспользуюсь преимуществами использования этого инструмента, по крайней мере, в такой ситуации.
Конечно, другие сталкивались с подобными ситуациями. Я надеюсь, что кто-то, кто «был там, сделал это», может поделиться какой-то мудростью. :-)
Так вот в чем вопрос ... Какой подход следует предпочитать в этой ситуации? Зачем? Есть ли лучший вариант, который я не рассмотрел?