Monday, October 6, 2014

NHibernate: Copy an object graph

We are working on an application where we have to create copies of a whole object graph and save this copy as a new object(or better an object tree) to the database.

I found 2 possible solutions to get this done:

Option 1 – Serialize and deserialize the object tree

This is probably the easiest solution. Take the object tree you want to copy, serialize it, deserialize it and attach it to an NHibernate session. The only caveat is that every object in your object tree should be marked as [Serializable].

Option 2 – Combining an ID reset, Session.Evict and some dependency walking

Another option is to walk through the object tree yourself while resetting the id values to their default. Don’t forget to remove the objects from the session first by calling Session.Evict.

2 comments:

David Albrecht said...
This comment has been removed by the author.
David Albrecht said...

Thanks for your blog post.

As a general question about NHibernate, I've been wondering: do people make multiple in-memory copies of the same database object?

Let's say I have a database object loaded into memory via NHibernate. I want a copy of this I can edit/trash/mess up and then either persist it, or just throw it away if I don't want to save it.

The trouble is, when I implement copy constructors on my entities, I end up copying a lot of proxy objects and this keeps throwing exceptions, because apparently proxies can't be copied like full-on POCOS -- I suspect due to them being "shadows" of the real objects without all their properties and data loaded. So I think when my code tries to access a property of a proxy, NHibernate tries to load the full object (represented by the proxy) from the database but it can't, because there's no open session.

How do people handle this? Do they not implement copy constructors for NHibernate objects? Perhaps they end up special-casing their copy constructors to tiptoe around proxies and not make full copies of them? Any thoughts would be helpful.

Regards, DA