Situation
Assume:
- NHibernate 4
- A parent/child relationship (one-to-many), uni-directional mapping from parent to child
Inverse(false)
, i.e. the parent is responsible for the associationCascade.All
from parent to child- Versioning (database column that the DB auto-increments when record is updated) enabled for both parent and child (optimistic locking)
Observed behavior:
- Open session and transaction.
- Load some parent object together with its child collection via some query.
- Add a newly created child to the child collection.
SaveOrUpdate
the parent.- NHibernate first adds the child to the database, giving it a version.
- It then takes care of the parent's association (because it is responsible for it) and updates the foreign key of the child (thank god it was nullable...), increasing the child's version. However, it does not update the child in the session.
- Finally it applies cascading and also calls
AddOrUpdate
on the child. Only problem: It has an outdated version of it in the session, causing aConcurrencyException
to be thrown. NHibernate is shooting itself in the foot.
Question
Why does NHibernate not update the child objects in the session when it applies the logic to update the association? What is the rationale behind it? It seems to me that the only reasonable way to model parent/child with versioning is to use Inverse(true)
.
Clarification: I am not interested in any workaround and/or more appropriate configuration. I know about those. I am only interested in the reasoning behind NHibernate's behavior in the described scenario.
Edit: The main problem seems to be (imo) that NHibernate doesn't fully control the versioning by itself. Rather, it let's the database take care of it (in my configuration at least). Unfortunately, this doesn't play well together, because NHibernate does not anticipate a version change in the client when it updates the association to it, because from a higher level view, the association belongs to the parent and therefore no change in the child is expected. This is at least a possible rationale behind it.