0

在对我的映射进行了一些更改之后( 有关原因,请参阅我关于级联删除的其他问题),我尝试插入一个全新的对象及其所有子类。

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

我有一个带有 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 的映射

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

第二个集合中对象的映射映射与上述类似。设想的情况是,我保存父级,这将触发子类/集合的保存。

例如,我有 ID = 1 的 Parent,Parent 填充了 1 个集合,并且这个集合有自己的 1 个集合。

所以我保存父级,父级从数据库中获取一个 ID(本机 sql 身份)。现在,第一个集合应该将其 ParentID 属性填充为 Parent 刚从数据库中获得的 ID。并且该集合的集合应该使用 Child 从数据库中获取的 ID 填充其 ChildID,其方式与 Parent 获取其 ID 的方式相同。

现在发生的事情是(我在 NHProf 中检查了创建的 SQL)所有内容都被插入,具有自己的 ID,但是集合没有用其父类的 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

带有内部异常 {"Object does not match target type."}

可悲的是,这个错误并没有让我知道从哪里继续。

4

2 回答 2

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"/>
于 2010-03-09T18:38:11.693 回答
0

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

问题在于我无法到达<Document>从数据库中获取他的密钥的场景,然后在一次调用<generator class="native"/>中将此密钥插入其基础类的外键属性中。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;
                }
            }
        }
    }
于 2010-03-11T09:55:23.080 回答