nhibernate mapping не сохраняет / вставляет ключи вставленных подклассов - PullRequest
0 голосов
/ 09 марта 2010

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

После этого возникла другая проблема - проблема с вставкой ключей в базу данных. Ситуация выглядит следующим образом:

У меня есть объект с 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

Отображение объекта коллекции

<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 ]

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

Я думаю, было бы полезно, если бы вы также показали нам свои уроки. Проверяли ли вы, что ваш родительский класс действительно имеет свойство ParentID типа Parent, также я предполагаю, что вы сейчас удалили

<property name="ParentID" column="ParentID" not-null="true"/> 

из вашего сопоставления и заменили его множеством к одному? Наконец, если вы хотите, чтобы у ваших дочерних объектов были коллекции дочерних объектов, тогда дочернему объекту также потребуется много-к-одному

<many-to-one name="CollectionObjectParent"
             class="CollectionObject,CollectionObject-ns"
             column="ChildID"
             not-null="true"/>
0 голосов
/ 11 марта 2010

К сожалению, после игры с отображениями и чтения через половину интернета, я не смог решить эту проблему.

Проблема заключается в том, что я не могу добраться до сценария, когда <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;
                }
            }
        }
    }
...