This is a migrated thread and some comments may be shown as answers.

Quick way to copy\duplicate an object?

13 Answers 611 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
sitefinitysteve
Top achievements
Rank 2
Iron
Veteran
sitefinitysteve asked on 24 Feb 2011, 08:13 PM
Is there an easy way to duplicate an object aside from

newObject.Property1 = oldObject.Property1;
newObject.Property2 = oldObject.Property2;
newObject.Property3 = oldObject.Property3;
....

? :)

13 Answers, 1 is accepted

Sort by
0
PetarP
Telerik team
answered on 02 Mar 2011, 07:35 PM
Hello Steve,

That pretty much depends on the copy you would like to achieve. One way would be to inherit from the IClonable interface and implement its only method Clone. Using that method you should be able to make clones of your persistent objects.

Best wishes,
Petar
the Telerik team
Registration for Q1 2011 What’s New Webinar Week is now open. Mark your calendar for the week starting March 21st and book your seat for a walk through all the exciting stuff we ship with the new release!
0
Shawn Krivjansky
Top achievements
Rank 1
answered on 11 Oct 2011, 11:38 PM
I have been dealing with this problem as well recently and thought I'd chime in.

Yes, implementing an "ICloneable" startegy helps a little, but it won't be a full solution if your object is more than just a couple simple fields and you are dealing with more than one context.

For example, if you have any association properties (FKs) or worse collection properties (LISTs 1:many), implementing any kind of "memberwiseclone" will run you into problems.  Presumably, the reason that you are "copying" an object to begin with is to ADD the "new" object to a context.  If you started a context and want to add the "new" object after the cloning to that same context, you should be ok, but try that same thing to a NEW/SEPARATE context.  It will fail (complaining that certain objects are managed by more than one context.)  That is the scenario I am currently facing.  I'm copying objects from one database to another (i.e. from one CONTEXT to another).  My objects have a lot of these "reference" types (FK associations/ILists)... that do not get "copied" per se during a memberwiseclone... the REFERENCE (to the original object/context) gets copied.  When I take that old reference/context and try to add it to my new context, it blows up with the "...managed by more than one context" exception.

The FK association properties can be dealt with a little, but the ILIST collections are by default marked as "READ ONLY"...and the reason I say they are "worse".  I cannot find a way to remove that "reference" once it is there (i.e. after I would do a memberwiseclone).  After my memberwiseclone (fills in ALL my properties and saves me time), I just want to set that stupid collection property to NOTHING/NULL to get rid of the reference to that old context. (No, .Clear() will NOT clear the "reference", only the items from the collection.)  I have a ticket out to telerik asking about this situation to see if there is anything I can do, because it is pretty anoying...  Not sure if some kind of overriding in the partial class can be done without any harm or not.

As a result, currently what I'm doing is NOT using the memberwiseclone and coping field by field without assigning anything to the collection properites.  That's a lot of typing and not a solution I'm very happy about....hence the ticket to Telerik to see if there is a better way.  I just thought I'd document my experiences here for the communitiy in case anybody has any insight or can benefit from reading.
0
PetarP
Telerik team
answered on 14 Oct 2011, 03:24 PM
Hello Shawn Krivjansky,

As my college already shared with you in a support ticked this will be an API that we are working on and will release in the near future that will handle  the data transfer via (de)serialization. As for the manual approach trying to clone the objects, there is really not much better approach than the one you currently have. 
The API we are about to release will be based on the object container. Please bear in mind that it is still in the process of development and I cannot give you an exact time frame when it will be ready.

All the best,
Petar
the Telerik team

Check out the latest stable build of Telerik OpenAccess ORM. Download it and benefit from our new Project Templates.

0
Andrew
Top achievements
Rank 1
Veteran
Iron
answered on 05 Jun 2012, 01:19 PM
has this cloning been implemented? I would like to be able to clone my whole entity w/children and insert it into the database.
if so do you have examples?

Thanks,
0
PetarP
Telerik team
answered on 08 Jun 2012, 03:16 PM
Hi Andrew,

 We are about to release the Q2 version of OpenAccess that will have support for Attach/Detach scenarios. Using this functionality you will be able to create complete object graph copies of your objects. The release is scheduled for Monday next week.

Greetings,
Petar
the Telerik team
Follow @OpenAccessORM Twitter channel to be the first one to get the latest updates on new releases, tips and tricks and sneak peeks at our product labs!
0
Andrew
Top achievements
Rank 1
Veteran
Iron
answered on 08 Jun 2012, 03:41 PM
Great thanks,

Will you have examples?

also I had implemented a generic copy method using serialization/refelection/recursion and it worked great except that we have some lookup type tables that their items would also get duplicated upon saving and should not be.
0
PetarP
Telerik team
answered on 11 Jun 2012, 01:32 PM
Hi Andrew,

 You can find some examples in our online documentation here. Also please note that the new Q2 release has been released and is available for download.

All the best,
Petar
the Telerik team
Follow @OpenAccessORM Twitter channel to be the first one to get the latest updates on new releases, tips and tricks and sneak peeks at our product labs!
0
Erik
Top achievements
Rank 2
answered on 20 Nov 2013, 07:19 PM
Hi Petar,

When I try this, I get an exception:
Object references between two different object scopes are not allowed. The object 'DossierData' is already managed by 'ObjectScopeImpl 0x25' and was tried to be managed again by 'ObjectScopeImpl 0x24 OpenAccessRuntime.EnlistableObjectScope'.

I tried it like this:
Dim ent_DossierDataOld As DossierData = [...get entity...]
Dim ent_DossierDataNew As DossierData = Connection.CreateDetachedCopy(Of DossierData)(ent_DossierDataOld)
ent_DossierDataNew.Version = ent_Version.Version                              
Connection.Add(ent_DossierDataNew)

Thanks in advance,

Erik
0
Ady
Telerik team
answered on 26 Nov 2013, 09:37 AM
Hi Erik,

Sorry for the delayed reply.

Is the 'Version' a reference property? If yes, then you need to specify that in the call to 'CreateDetachedCopy'. It seems that since you have not specified the reference fields in the call to 'CreateDetachedCopy' the detached copy is flat. You then assign the reference from old to new and add the new object to another context. The 'Version' property also needs to be detached and attached to the new object.

Hope this helps. Do get back in case you need further assistance.

Regards,
Ady
Telerik
OpenAccess ORM Q3 2013 simplifies your model operations even further providing you with greater flexibility. Check out the list of new features shipped with our latest release!
0
Lagrange
Top achievements
Rank 1
answered on 22 Sep 2015, 10:51 AM

Hi Ady,

This is an old thread, but I'm facing a similar issue.

I want to duplicate a row in my database, with very few changes.

I've try this :

var existing = RedactionActe.Instance.Mapping.Biens.FirstOrDefault(b => b.IdBien == IdObjet);
var newObject = RedactionActe.Instance.Mapping.CreateDetachedCopy(existing, "Adresses");
newObject.Numero = Compteur.Increment(RedactionActe.Instance.Mapping, Compteur.BIENS);
newObject.DenominationLatin = "Copie de " + newObject.DenominationLatin;
newObject.TitreFoncier = "Copie de " + newObject.TitreFoncier;
RedactionActe.Instance.Mapping.AttachCopy(newObject);
RedactionActe.Instance.Mapping.SaveChanges();

The "Bien" object has several references, but I'm only copying the "Adresses" collection.

This code... update the original object.
When replacing AttachCopy<T>() by Add<T>(), I have the same scope exception than Erik.

 

Can you show me the good way ?

Thanks.

0
Simeon Simeonov
Telerik team
answered on 25 Sep 2015, 10:11 AM
Hello Lagrange,

Thank you for your question.

The reason the original entity is updated when you are attaching the copy-entity is that DataAccess is able to recognize that this is the originally managed entity (it recognizes that this entity is related to a specific record in the database) and treats the changes made as updates on the original entity.

If you want to create a full copy of the original entity and add the copy-entity to the context in such a way that  a new record is created in the database we recommend that you use the serialize/deserialize pattern. The idea is to decorate the persistent class(es) with the Serializable attribute and to implement the ISerializable interface. This process will wipe the relation between the entity and a specific record in the database and after that when you add it to the context it will treat it as a new record. For that you can use code similar to this one:
using (var context = new FluentModel())
{
    Car car = context.GetAll<Car>().First(c => c.CarID == 1);
    Car carCopy = new Car();
    using (MemoryStream serializationStream = new MemoryStream())
    {
        BinaryFormatter formatter = new BinaryFormatter();
        formatter.Serialize(serializationStream, car);
        serializationStream.Position = 0;
        carCopy = (Car)formatter.Deserialize(serializationStream);
    }
 
    carCopy.Model = "Copy - " + carCopy.Model;
 
    context.Add(carCopy);
    context.SaveChanges();
}

The main thing you need to determine is which part of the entity tree you want to full copy and which part you want to reuse. More specifically you need to determine what you want to do with the reference properties and the collections. For example if you want to make a full copy of the "Addresses" collection you can make a detached copy like you are currently doing (with the "Addresses" collection) and then serialize/deserialize the detached copy. On the other hand if you want the copy-entity to point to the same Addresses as the original entity, you will need to populate the "Addresses" collection of the deserialized-copy with a loop from the original entity.

I hope this information helps you.

Regards,
Simeon Simeonov
Telerik
 
Check out the latest announcement about Telerik Data Access vNext as a powerful framework able to solve core development problems.
0
Lagrange
Top achievements
Rank 1
answered on 12 Oct 2015, 04:17 PM

Hi Simeon,

 

Thanks, this work fine after a little practice.

This said, is it possible ​ to have an overload of CreateDetachedCopy(), who create a... really detached copy ? I don't know if you reference all objects dependant of the model, or if the object references your internal model. Anyway, it may not be very complicated for you to do so.

Regards,

Romain Lagrange

0
Simeon Simeonov
Telerik team
answered on 13 Oct 2015, 11:17 AM
Hi Lagrange,

I am glad the solution worked for you.

Thank you for your suggestion regarding the CreateDetachedCopy overload. I am afraid that such a change would not fit the intent of the method. The main purpose of the method is to allow you to detach an entity from a given context, send it to some remote consumer and attach it there again. The CreateDetachedCopy method was specially constructed in such a way that when you attach the copy later into another context, it will be able to identify the related record and update it accordingly. This is why such change will no longer allow the method to be used in its main use case.

Regards,
Simeon Simeonov
Telerik
 
Check out the latest announcement about Telerik Data Access vNext as a powerful framework able to solve core development problems.
Tags
General Discussions
Asked by
sitefinitysteve
Top achievements
Rank 2
Iron
Veteran
Answers by
PetarP
Telerik team
Shawn Krivjansky
Top achievements
Rank 1
Andrew
Top achievements
Rank 1
Veteran
Iron
Erik
Top achievements
Rank 2
Ady
Telerik team
Lagrange
Top achievements
Rank 1
Simeon Simeonov
Telerik team
Share this question
or