views:

54

answers:

2

I am using Nhibernate (I am a complete noob), and what I want to be able to do is copy an entity that is loaded from the database and save it with a new Id... has anyone run into this situation? Any help would be very appreciated.

+1  A: 

I need to do exactly this for a very complex set of objects and what I have found so far is:

NHibernate does not exactly support this.

If you try to simply replace the Id of an object you got from a session, you will get an Nhibernate error: identifier of an instance of was altered from <9ae3868d-17bf-4314-ba0c-4eb3b44b1a2e> to <2b2b67c6-a421-48c4-836c-4c27f6481718>

If the session no longer knows about the objects it retrieved, i.e if you evict them before saving and flushing, just changing the ids will now work. So you could write code like this:

 public void CloneStudent(Guid studentId)
    {
        // Get existing student
        Student student = _session.Get<Student>(studentId);

        // Copy by reference
        Student newStudent = student;

        // Reset Id to do quick and dirty clone
        newStudent.Id = Guid.NewGuid();
        newStudent.Sticker = "D";

        // Must evict existing object or Nhibernate will throw object modified error
        _session.Evict(student);

        // Save new object
        _session.Save(newStudent);
        _session.Flush();


    }

The problem with this is if your object graph has any depth you have to be sure to evict the entire set, and then you may need the originals in the session still you have to retrieve them again. This is a logistical headache and yields code with very obscure and convoluted intentions.

I do not recommend.

What is more commonly done is serialize to a binary stream and reconstitute this stream into a new set of objects. Fine, but only works if your objects are all serializable.

That is not the case for me, what I am doing is I wrote manual code to make deep copies of an object graph using copy constructors. This is complex and also can lead to maintenance issues, but if the objects cannot be serialized there are few better alternatives.

Sorry, deep copying objects remains a complicated task if serialization is not an option.

Sisyphus
Thanks for the suggestions Sisyphus, I was afraid of what you just suggested, but luckily I have the convenience of having all my entity objects being serializable. I will give it a try and let you know how it works out.
PCG
+2  A: 

Just do new MyClass() and copy everything except the Id. You can use reflection for that.

Diego Mijelshon
+1: This is what we do; you can use automapper or valueinjecter to perform the copy as well; just have it ignore the id (obviously).
DanP