nhibernate mapping не сохраняет / вставляет ключи вставленных подклассов
После того, как я немного изменил свои отображения ( см. Мой другой вопрос о каскадном удалении по причинам), я попытался вставить совершенно новый объект и все его подклассы.
После этого возникла еще одна проблема - проблема с вставкой ключей в базу данных. Ситуация выглядит следующим образом:
У меня есть объект с 2 уровнями подклассов, оба коллекции.
Давайте назовем объект Parent, у этого есть коллекция потомков, и у каждого подразделения в этом собрании есть своя коллекция объектов. Которые отображаются следующим образом.
Родительское отображение его <set>
<!--Parent-->
<set name="Collection"
table="Table"
cascade="all-delete-orphan"
batch-size="15"
inverse="true">
<key column="ParentID"/>
<one-to-many class="CollectionObject,CollectionObject-ns"/>
</set
CollectionObject's Mapping
<id name="ID" column="ID">
<generator class="native"/>
</id>
<!-- property mappings-->
<property name="ParentID" column="ParentID" not-null="true"/>
<!--collection mapping-->
<set name="Collection"
table="Table"
cascade="all-delete-orphan"
inverse="true"
batch-size="15">
<key column="ChildID"/>
<one-to-many class="CollectionObject,CollectionObject-ns"/>
</set>
Отображение отображения объекта во 2-й коллекции аналогично приведенному выше. Предполагаемый сценарий будет, я сохраняю Родителя, это вызовет сохранение подклассов / коллекций.
Например, у меня есть Родитель с ID = 1, Родитель заполнен 1 коллекцией, и у этой коллекции есть 1 собственная коллекция.
Поэтому я сохраняю Parent, родитель получает идентификатор из базы данных (собственный идентификатор sql). Теперь первая коллекция должна получить свойство ParentID, заполненное идентификатором, который родительский объект только что получил из базы данных. И коллекция должна получить ChildID, заполненный идентификатором, который Ребенок получил из базы данных так же, как Родитель получил свой идентификатор.
Теперь происходит следующее (я проверил созданный SQL в NHProf). Все вставляется с собственным идентификатором, но коллекции не получают заполненную ключевую колонку с идентификатором родительского класса. (вместо этого просто вставляется 0)
Таким образом, мой вопрос сводится к тому, что я забыл добавить к своему отображению, что и должно произойти? Ключевой столбец не делает то, что я думаю, что он должен делать?
Если я забуду что-нибудь добавить, пожалуйста, так и скажите. Я с удовольствием предоставлю дополнительную информацию.
Обновить
Я думаю, что проблема может быть связана с детьми, не имеющими <many-to-one>
тег. Поэтому я попытался добавить один из них к первому дочернему сопоставлению. Я придумал это
<many-to-one name="ParentID"
class="Parent,Parent-ns"
column="ParentID"
not-null="true"/>
Тем не менее, эта настройка дает мне следующую ошибку.Exception occurred getter of Parent.ParentID
с InnerException{"Object does not match target type."}
К сожалению, эта ошибка не дает мне никаких идей о том, где продолжить.
2 ответа
Я думаю, что было бы полезно, если бы вы могли также показать нам свои уроки. Проверяли ли вы, что ваш родительский класс действительно имеет свойство ParentID типа Parent, также я предполагаю, что вы сейчас удалили
<property name="ParentID" column="ParentID" not-null="true"/>
из вашего картографирования и заменили его множеством к одному? Наконец, если вы хотите, чтобы ваши дочерние объекты имели коллекции дочерних объектов, тогда дочернему объекту также понадобится много-к-одному
<many-to-one name="CollectionObjectParent"
class="CollectionObject,CollectionObject-ns"
column="ChildID"
not-null="true"/>
К сожалению, после игры с отображениями и чтения через половину Интернета я не смог решить эту проблему.
Проблема заключается в том, что я не могу добраться до сценария, который <Document>
получает свой ключ из базы данных <generator class="native"/>
и после этого вставляет этот ключ в свойства foreignkey его базовых классов, внутри всего одного session.Save()
вызов.
например, для сценария я хотел бы session.Save(document)
- * обнаружен новый документ - * получить новую личность
- * Документ имеет подкласс с иностранным ключом к нему!
- * вставить идентичность в указанные свойства чужих ключей (думаю, здесь кроется проблема)
и повторите это со всеми основными классами.
Тем не менее, я нашел обходной путь (самый уродливый код за всю историю, но он справился с работой). Я не очень хочу делиться этим дерьмовым кодом, но он может просто помочь людям, читающим здесь.
Я еще не разочаровался в правильном решении этого вопроса, но на данный момент это нужно сделать. Все еще открывай для лучшего движения.
входящий код дерьма!
public void InsertDocument(Document document)
{
using (ISession session = NHibernateHelper.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
try
{
IDocument document2 = new Document();
document2.Bodyregels = document.Bodyregels;
//for making the query a little neater
document.Bodyregels = null;
//lets get the elusive identity
session.Save(document);
session.Flush();
//reattach subclass and enter the id explicitly
document.Bodyregels = document2.Bodyregels;
foreach (DocumentBodyregel dbr in document.Bodyregels)
{
dbr.DocumentID = document.DocumentID;
}
//save it again, now with filled FK
session.Save(document);
session.Flush();
//now save the final subclass with FK's
foreach (DocumentBodyregel dbr in document.Bodyregels)
{
foreach (DocumentBodyregelWaarde dbrw in dbr.Waardes)
{
dbrw.RegelID = dbr.ID;
dbrw.DocumentID = document.DocumentID;
}
}
//and save the entire thing again (now with FK's)
session.Save(document);
transaction.Commit();
}
catch (Exception e)
{
transaction.Rollback();
throw e;
}
}
}
}