0

I have this mapping in one class:

<class name="Parent">
<set name="Activity" table="ChangeLogs" order-by="ChangeDate desc" cascade="all-delete-orphan">
  <key column="RequestID" />
  <one-to-many class="ChangeLog" />
</set>

And this in the other:

<class Name="Child">
<many-to-one name="Request" class="Request" column="RequestID" />

In the parent, loaded in the current transaction I add to the collection:

parent.Activity.Add(new Child(){/* properties, etc */});

And then I commit the transaction. Any changes to the parent get saved to the database with an update call, but I can't get those children to insert, regardless of cascade values or inverse=true/false/just-save-already. I've been bashing my head against it for a while, reading examples / documentation / etc, and I can't see why it wouldn't work. Am I missing something simple? I've been killing off the server and re-building after every change to make sure things are updating, but nada.

To make matters worse, occasionally it has worked, with various values for inverse, sometimes by adding the Request=parent to the child, sometimes by saving the child separately before adding... and then it quits working later on. I'm boggling o_O

edit: Things tried explicitly since this was posted, rebuild + server restart between every one, none of which generate an insert call or errors:

<set inverse=true>
parent.Activity.Add(new Child(){Request=parent})
<set inverse=true>
parent.Activity.Add(new Child(){})
<set>
parent.Activity.Add(new Child(){Request=parent})
<set>
parent.Activity.Add(new Child(){})
<set inverse=false>
parent.Activity.Add(new Child(){Request=parent})
<set inverse=false>
parent.Activity.Add(new Child(){})

This did work:

<set>
Child c = new Child() {Request = parent};
parent.Activity.Add(c);
Session.Save(c);

But then what's the point of setting a cascade if it's ignored?

edit: after reading a bit of this: http://nhibernate.info/doc/nh/en/index.html#example-parentchild-bidir I tried:

<class Name="Child">
<many-to-one name="Request" class="Request" column="RequestID" not-null=true />

with all 6 of the main ones above, with no luck.

Owen Pauling
  • 11,349
  • 20
  • 53
  • 64
Groxx
  • 2,489
  • 1
  • 25
  • 32

2 Answers2

1

For me it's always a problem to set it properly at one go. At first everything looks good in your code, but I'm actually wondering on which side you are setting the inverse property?

This code works for me:

<class name="Parent" table="Parent">

<bag name="Languages" inverse="true" cascade="all-delete-orphan" lazy="false" fetch="join">
  <key column="parentId" />
  <one-to-many class="Language" />
</bag>

<class name="Language" table="Language">

<many-to-one column="parentId" name="Parent" class="Parent" not-null="true" />

I hope this helps.

MonkeyCoder
  • 2,600
  • 2
  • 28
  • 30
  • Apologies if it wasn't clear. Inverse is only being set on the parent tag (not using a bag). Setting one on the many-to-one side gives me a schema error, so that's an option either way. From everything I've seen, it *should* work. But it's not. I've got it set to "none" and I'm doing it by hand now, but I don't understand why it's not working... – Groxx Mar 26 '11 at 09:01
  • Maybe the problem is more mapping related (not .hbm) - I'm running the above example on NHibernate version 2.1.2 and my bag is a IList. How do you instantiate your parent and activities collection? In my code I'm fetching the parent by id and adding languages to the collection in the same way as you do. At the end of the block I'm calling update on the parent and commiting the transaction. – MonkeyCoder Mar 26 '11 at 09:42
  • I do ISet<>, with HashedSet<>s, and I've tried calling update and not calling update (it's not necessary to do so, the dirty flags are enough). nada. – Groxx Mar 29 '11 at 06:45
0

This is the correct mapping:

<class name="Parent">
  ...
  <set cascade="all-delete-orphan" inverse="true" ...>
  ...
  </set>
</class>
<class name="Child">
  ...
  <many-to-one .../>
</class>

And the correct usage (assumes an already existing parent):

using (var tx = session.BeginTransaction())
{
    var parent = GetParent();
    parent.Collection.Add(new Child { Parent = parent });
    tx.Commit();
}
Diego Mijelshon
  • 52,548
  • 16
  • 116
  • 154
  • That's what I've thought it should be... any suggestions on debugging this, as it pretty clearly shouldn't be happening? I have the NHibernate source attached to my project, so I can head to any location, but that's hours and hours of random casting around to find the location, and then hours more to understand it :/ – Groxx Mar 29 '11 at 06:44