Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I copy an object with NHibernate

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.

like image 956
PCG Avatar asked Oct 29 '10 22:10

PCG


2 Answers

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

like image 99
Diego Mijelshon Avatar answered Sep 24 '22 21:09

Diego Mijelshon


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.

like image 44
Sisyphus Avatar answered Sep 25 '22 21:09

Sisyphus