NHibernate using Cascade to merge disconnected objects

Recently, I ran into an issue where I was getting a list of objects separately (and not from NHibernate) and setting the parent objects IEnumerable equal to this returned object. I am not sure if it is an anti-pattern, but our legacy application often needs to create or update an object (not from NHibernate) and then save it, we merge the object before calling save. This way, new objects, existing objects in the NHibernate cache, as well as existing objects NOT in the NHibernate cache all get saved properly.
This is our NHibernate save method:


[Transaction]
public int? Save(DocumentFieldDTO entity, bool autoFlush)
{
var persisted = CurrentSession.Merge(entity);

entity.DocumentFieldID = persisted.DocumentFieldID;
if (autoFlush) { CurrentSession.Flush(); }
return entity.DocumentFieldID;
}

The DocumentFieldDTOMap looked like this:


public class DocumentFieldDTOMap : EntityMapBase
{
public DocumentFieldDTOMap()
{
Table("DocumentField");

Id(m => m.DocumentFieldID).GeneratedBy.Increment().UnsavedValue(null);

Map(x => x.Name);

Map(x => x.DocumentSectionID).Not.Update();
// .... Lots of other fields ....//

HasMany(x => x.DocumentFieldOrgs)
.Cascade.SaveUpdate()
.LazyLoad()
.KeyColumn("DocumentFieldID");
}

The problem was the merge would not update the child objects if they were not retrieved with NHibernate. The parent object would get updated. The children would be updated if retrieved with NHibernate; however, it would happily continue without error and not make any changes to the children. We could not use “SaveOrUpdate()” in the save, because of the reasons mentioned above. In some scenarios, we could get an exception when saving objects that are not in the NHibernate cache.

The fix is simple, but I am concerned about the consequences. If you change “Cascade.SaveUpdate()” to “Cascade.All()” it will work. I am concerned because I am not sure if I don’t want to cascade deletes. I am going to write a test to ensure that deletes do not get cascaded. If it doesn’t work, I will have to find another option.

This entry was posted in Development. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *