У нас есть довольно большая БД (~ 200 таблиц), которая почти полностью использует составные первичные ключи и составные внешние ключи, используя одну «базовую таблицу», от которой каждая другая таблица наследует часть своего первичного ключа:
- Родитель имеет первичный ключ из одного столбца ParentId
- Дочерний имеет составной первичный ключ (ParentId, ChildId) и внешний ключ ParentId
- У племянника есть составной первичный ключ (ParentId, NephewId), внешний ключParentId и внешний ключ (ParentId, ChildId)
и так далее.До сих пор мы управляли всем этим shebang с помощью собственной платформы ORM, но мы рассматриваем возможность использования NHibernate, который мне поручено изучить (я скачал v2.1.2).
Отображения: Ребенок
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Assembly" namespace="Namespace">
<class name="Child" table="Child">
<composite-id name="IdChild" class="ChildId">
<key-many-to-one name="Parent" column="ParentId" class="ParentId"></key-many-to-one>
<key-property name="Id" column="ChildId" type="Int32"></key-property>
</composite-id>
<!--simple properties-->
<set name="Nephews" table="Nephew">
<key>
<column name="ParentId"></column>
<column name="ChildId"></column>
</key>
<one-to-many class="Nephew"/>
</set>
</class>
</hibernate-mapping>
Племянник
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Assembly" namespace="Namespace">
<class name="Nephew" table="Nephew">
<composite-id name="IdNephew" class="NephewId">
<key-many-to-one name="Parent" column="ParentId" class="Parent"></key-many-to-one>
<key-property name="Id" column="NephewId" type="Int32"></key-property>
</composite-id>
<many-to-one name="Child" class="Child">
<column name="ParentId"></column>
<column name="ChildId"></column>
</many-to-one>
<!--simple properties-->
</class>
Я могу также публиковать классы, если вы хотите, я опущу их сейчас для краткости (как я будуопустите отображение для Родителя, так как у него нет проблем).Каждое свойство является виртуальным, каждый файл сопоставления является встроенным ресурсом, каждый составной Id имеет свой собственный класс, который переопределяет Equals и GetHashCode.
Проблема в том, что я не могу сохранить экземпляр Nephew, инициализированный с помощью простого new Nephew()
и передан _session.Save()
, потому что я получаю System.IndexOutOfRangeException: Invalid index n for this SqlParameterCollection with Count=n.
.
Единственный столбец, который дублируется в отображении, это ParentId
.Удаляя отображение many-to-one
в Nephew
, отображение set
в Child
и все связанные свойства, все работает нормально.
Я нашел несколько сообщений, сообщающих об этом исключении, и наиболее подходящее в моемКажется, дело в , в этом , что дает мне внутреннее ощущение, что моя текущая схема недопустима с NHibernate.Пожалуйста, скажите мне, что я не прав: -)
ПРИМЕЧАНИЯ:
- Я сейчас не использую Fluent, хотя это может быть вариантом, но я предпочел изучить основыfirst;
- Да, мы понимаем, что составные первичные ключи - большая боль в заднице.Эта БД прошла через несколько раздач в течение многих лет, вероятно, не столь опытных, но перед ее рефакторингом мы будем считать до 10 000