nhibernate mapping does not save/insert keys of inserted subclasses
After having changed around my mappings a bit ( see my other question about cascade-delete for reasons) , i tried inserting a completely new object and all its subclasses.
After this another problem emerged, an issue with the insertion of the keys into the database. Situation is as follows:
I have an object with 2 tiers of subclasses, both a collection.
lets call the object Parent, this one has a collection of childs, and every enitity in this collection has its own collection of enitities. Which are mapped as follows.
Parent's mapping of its <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>
The mapping mapping of the object in the 2nd collection is similar tot he above. The envisioned scenario would be, I save Parent, this would trigger the save of subclasses/collections.
e.g. I have Parent with ID = 1, Parent is filled with 1 collection, and this collection has 1 collection of its own.
So I save Parent, parent gets an ID from database (native sql identity). Now the first collection should get its ParentID property filled with the ID the Parent just got from the database. And the collection of the collection should get its ChildID filled with the ID the Child got from the database in the same way as Parent got his ID.
What happens now is (I checked created SQL in NHProf) Everything gets inserted, with its own ID, But the collections do not get their keycolumn filled with the ID of their parentclass. (instead it just gets 0 inserted)
So my question boils down to, what did i forget to add to my mapping which causes the to happen? Does the key column not do what i think it should do?
If i forget to add anything here, please say so. I will gladly give additional information.
update
I think the problem might have to do with the childs not having a <many-to-one>
tag. So i tried to add one of those to the first child mapping. I came up with this
<many-to-one name="ParentID"
class="Parent,Parent-ns"
column="ParentID"
not-null="true"/>
However, this setup gives me the following error.
开发者_开发技巧Exception occurred getter of Parent.ParentID
with InnerException
{"Object does not match target type."}
Sadly, This error does not give me any ideas of where to continue.
I think it would be helpful if you could show us your classes as well. Have you checked that your Parent class really has a ParentID property of the type Parent, also I assume you have now removed the
<property name="ParentID" column="ParentID" not-null="true"/>
from your mapping and replaced it with the many-to-one? Finally if you want your child objects to have collections of child objects then the child object will also need a many-to-one
<many-to-one name="CollectionObjectParent"
class="CollectionObject,CollectionObject-ns"
column="ChildID"
not-null="true"/>
Sadly, after playing around with mappings and reading trough half the internet, I have not been able to solve this.
The problem lies in the fact that i cant get to the scenario that <Document>
gets his key from the database <generator class="native"/>
and after this Inserts this key into the foreignkey properties of its underlying classes, inside just one session.Save()
call.
e.g. for scenario i'd like session.Save(document)
-- * new document detected -- * get new identity
-- * document has subclass with a foreignkey to it!
-- * insert idenity into the specified foreignkey properties (guess here lies the problem)
and repeat this with all underlying classes.
I did however come up with a workaround (most ugly code ever, but it gets the job done) Im not really into sharing code this crappy, but it just might help people reading here.
I have not yet given up on solving this the right way, but for the moment this has to do. Stil open for a nudge in the better direction.
incoming crap code!
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;
}
}
}
}
精彩评论