nhibernate映射不保存/插入插入的子类的键

时间:2010-03-09 09:28:29

标签: nhibernate nhibernate-mapping one-to-many foreign-keys many-to-one

稍微改变了我的映射( see my other question about cascade-delete for reasons)后,我尝试插入一个全新的对象及其所有子类。

在此之后出现了另一个问题,即将密钥插入数据库的问题。情况如下:

我有一个包含2层子类的对象,这两个都是一个集合。

让我们调用对象Parent,这个对象有一个子集合,这个集合中的每个enitity都有自己的enitities集合。其映射如下。

家长对其<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的映射

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

第二个集合中对象的映射映射与上面的类似。 设想的场景是,我保存Parent,这将触发子类/集合的保存。

e.g。我有ID为1的Parent,Parent有1个集合,此集合有1个集合。

所以我保存Parent,parent从数据库中获取一个ID(本机sql标识)。现在第一个集合应该让它的ParentID属性填充Parent从数据库中获得的ID。并且该集合的集合应该使其ChildID以Child与其获取其ID相同的方式填充Child从数据库获取的ID。

现在发生的事情是(我在NHProf中检查了创建的SQL)所有东西都被插入,带有自己的ID,但是集合没有让他们的keycolumn填充其父类的ID。 (相反它只是插入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 个答案:

答案 0 :(得分:1)

我认为如果您能向我们展示您的课程将会有所帮助。您是否检查过您的Parent类确实具有Parent类型的ParentID属性,我还假设您已经删除了

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

从您的映射中将其替换为多对一?最后,如果您希望子对象具有子对象的集合,那么子对象也需要多对一

<many-to-one name="CollectionObjectParent"
             class="CollectionObject,CollectionObject-ns"
             column="ChildID"
             not-null="true"/>

答案 1 :(得分:0)

可悲的是,在玩过映射并阅读半数互联网之后,我无法解决这个问题。

问题在于我无法进入<Document>从数据库<generator class="native"/>获取密钥的情况,并在此之后将此密钥插入其基础类的foreignkey属性中,一个session.Save()电话。

e.g。我喜欢session.Save(document)

的情景

- *检测到新文件 - *获得新身份

- *文件有子类,带有外键!
- *将标识插入指定的外键属性(猜猜这就是问题所在)

并对所有基础类重复此操作。

然而,我确实提出了一个解决方法(有史以来最丑陋的代码,但它完成了工作)我真的没有真正分享这个糟糕的代码,但它可能会帮助人们在这里阅读。

我还没有放弃以正确的方式解决这个问题,但目前还有这个问题。 Stil向更好的方向轻推。

传入的垃圾代码!

    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;
                }
            }
        }
    }