Help mapping a bag with NHibernate, items in bag not saving
I am having some trouble getting a List of one of my classes that is stored within another class.
I have a Class Intersection which is of a base type device that contains a List of Zones, another class of mine. Each Intersection can have multiple zones, but only 1 Intersection may be assigned to a specific zone.
My mapping for the Device/Intersection is as follows:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class xmlns="urn:nhibernate-mapping-2.2" name="EMTRAC.Devices.Device, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="`Device`" lazy="false">
<id name="PK" type="System.Int64, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="PK" />
<generator class="identity" />
</id>
<many-to-one class="EMTRAC.Connections.Connection, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="LocalConnection" lazy="false" cascade="all">
<column name="LocalConnection_id" />
</many-to-one>
<many-to-one class="EMTRAC.Connections.Connection, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="Connection" lazy="false" cascade="all">
<column name="Connection_id" />
</many-to-one>
<many-to-one class="EMTRAC.Packets.Packet, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="Configuration" lazy="false" cascade="all">
<column name="Configuration_id" />
</many-to-one>
<joined-subclass name="EMTRAC.Intersections.Intersection, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" lazy="false">
<key>
<column name="Device_id" />
</key>
<bag name="Zones" cascade="all-delete-orphan">
<key>
<column name="Intersection_id" />
</key>
<one-to-many class="EMTRAC.Zones.Zone, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</bag>
<many-to-one class="EMTRAC.Intersections.Streets, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="Streets" lazy="false" cascade="all">
<column name="Streets_id" />
</many-to-one>
<many-to-one class="EMTRAC.Positions.Position, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="Position" lazy="false" cascade="all">
<column name="Position" />
</many-to-one>
</joined-subclass>
And my mapping for the Zone class is as follows:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class xmlns="urn:nhibernate-mapping-2.2" name="EMTRAC.Zones.Zone, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="`Zone`" lazy="false">
<id name="ID" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="PK" />
<generator class="identity" /&开发者_如何学Cgt;
</id>
<property name="Active" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="Active" />
</property>
<property name="Dir" type="System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="Dir" />
</property>
<property name="IntID" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="IntID" />
</property>
<property name="Width" type="System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="Width" />
</property>
<many-to-one class="EMTRAC.Headings.Heading, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="Heading" cascade="all">
<column name="Heading_id" />
</many-to-one>
<many-to-one class="EMTRAC.Positions.Position, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="Start" cascade="all">
<column name="Start_id" />
</many-to-one>
<many-to-one class="EMTRAC.Positions.Position, EMTRAC_v3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="Finish" cascade="all">
<column name="Finish_id" />
</many-to-one>
Now, if I create a Zone object and save it to the database, everything saves just fine and the Intersection_Id field to reference to the Intersection object is null as expected. However, once I add this Zone object to the Intersection and save the Intersection, it doesn't link the Zone to the Intersection via the Intersection_id field, and loading the Intersection does not contain any zones in the List of Zones.
If I save the Intersection without first saving the zone, the Intersection saves fine, but the Zone is not saved.
Looking at the SQL for the session.Save(intersection), I do not see anything being sent to attempt to save the Zone.
Also, if I save the intersection then try a
foreach(Zone z in intersection.Zones) session.Save(z);
NHibernate doesn't execute any SQL and doesn't save the zone.
It's probably something small that I am missing. Any ideas?
EDIT
I actually found the solution to this. The mappings were in fact correct, or at least I am assuming they are since nothing looks blatantly wrong with them, although I don't know enough about NHibernate to determine why this solution worked.
Anyway, the solution was three-fold.
First I had to ensure that the Zone was saved before saving the Intersection with the list containing the Zone. If you don't save the Zone when calling the Flush, described below, you get an error when it tries to link the Zone to the Intersection but does not locate the Zone record in the table for the Zones.
This was accomplished by calling Session.Save(zone) where Session is an ISession.
After the Zone has been saved, I then saved the Intersection using the method above but calling Session.Save(intersection).
The final bit that solved the problem was after I saved the Intersection, I had to call Session.Flush() for the ISession, which then linked the Zone to the Intersection.
This solved the problem and now everything is saved, loaded, and linked correctly.
What does the ISession.Flush() do in the background that required me to call it to piece everything together and why was it not all saved simply calling Session.Save(intersection) with cascading set for the bag is the question?
in NH Updates and Inserts are normally batched and executed on Session.Flush()
, but since you're using identity
NH has to issue the INSERT immediatly to generate the id, but batches the Updates. to improve performance and enable batching there are other key generation strategies (GUID, HiLo, ...).
That zones are not Inserted at all inverse
might help
<bag name="Zones" cascade="all-delete-orphan" inverse="true">
精彩评论