Rizo's

nHibernate not updating child records when using Merge()

by on dec.15, 2011, under Developing

I had to run an update on some posts before I would do an insert. Then when I was about to do my insert, I got the error that the object was already in use.

SaveOrUpdate gave me that error, and ofc Update too. Merge worked BUT it only saved the parent object and not the child objects.

The connection though is that the child object is the one responsible to perform the save in the mapobject.

[sourcecode lang=”c#”]

HasMany(x => x.Info)
.Cascade.SaveUpdate();

[/sourcecode]
so I guess to be fair, it kinda works as intended.

The annoying part is that if you use SaveOrUpdate on a parent object, it will actually update the childs too as it understands the connection. But if you use Merge, it wont understand the connection at all!

Here’s a bit of that code

[sourcecode lang=”c#”]

public AlertEntity InsertCapAlerts(AlertEntity capMessage)
{

using (var transaction = _session.BeginTransaction(IsolationLevel.ReadCommitted))
{
var getCap = GetCapAlert(capMessage.Id);
if (getCap != null)
{
InfoEntity infoToSave = capMessage.Infos.FirstOrDefault();
_session.Merge(infoToSave);
_session.Merge(capMessage);
}
else
_session.Save(capMessage);

transaction.Commit();
return capMessage;
}
}

[/sourcecode]
Basicly, what I did is that when I get my new capMessage that I’m going to save, I first check if it already exists in the db. If it doesnt, then fine, just do a Save(). But if it does exist (here’s where SaveOrUpdate always crashed) then I just make a new instance of the child record (we only have one child, therefor FirstOrDefault()).

The first attempt I just saved the Child object to the db by using Merge (because SaveOrUpdate still gives me the error due the object being used in a previous session, and yes I did try session.Clear() and Flush and what not). It worked peachy but then I noticed that my childobject no longer points at its parent. So the childobject is now an orphan crying on the streets of the database. So what we need to do is to point the Parent ID again to the child object.

[sourcecode lang=”c#”]

InfoEntity infoToSave = capMessage.Infos.FirstOrDefault();
infoToSave.AlertEntity_id = capMessage.Id;
_session.Merge(infoToSave);
_session.Merge(capMessage);

[/sourcecode]
Why you ask? Because nHibernate is soooo cute that when it runs Merge, it doesn’t give a flying dutch about the childrecords (as it does when you run SaveOrUpdate as I mentioned before). So when you use Merge, you have to update all childposts yourself AND you have to point out the Parent again.

If anyone knows a better solution to this. Please do inform me. Otherwise, I hope that this little code example helped anyone in any way 🙂


24 Trackbacks / Pingbacks for this entry

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!