Quick way to copy\duplicate an object?

14 posts, 0 answers
  1. Steve
    Steve avatar
    1851 posts
    Member since:
    Dec 2008

    Posted 24 Feb 2011 Link to this post

    Is there an easy way to duplicate an object aside from

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

    ? :)
  2. PetarP
    Admin
    PetarP avatar
    754 posts

    Posted 02 Mar 2011 Link to this post

    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!
  3. DevCraft banner
  4. Shawn Krivjansky
    Shawn Krivjansky avatar
    86 posts
    Member since:
    Jan 2010

    Posted 11 Oct 2011 Link to this post

    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.
  5. PetarP
    Admin
    PetarP avatar
    754 posts

    Posted 14 Oct 2011 Link to this post

    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.

  6. Andrew
    Andrew avatar
    125 posts
    Member since:
    Sep 2008

    Posted 05 Jun 2012 Link to this post

    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,
  7. PetarP
    Admin
    PetarP avatar
    754 posts

    Posted 08 Jun 2012 Link to this post

    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!
  8. Andrew
    Andrew avatar
    125 posts
    Member since:
    Sep 2008

    Posted 08 Jun 2012 Link to this post

    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.
  9. PetarP
    Admin
    PetarP avatar
    754 posts

    Posted 11 Jun 2012 Link to this post

    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!
  10. Erik
    Erik avatar
    314 posts
    Member since:
    Feb 2008

    Posted 20 Nov 2013 Link to this post

    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
  11. Ady
    Admin
    Ady avatar
    588 posts

    Posted 26 Nov 2013 Link to this post

    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!
  12. Lagrange
    Lagrange avatar
    16 posts
    Member since:
    Sep 2010

    Posted 22 Sep 2015 Link to this post

    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.

  13. Simeon Simeonov
    Admin
    Simeon Simeonov avatar
    24 posts

    Posted 25 Sep 2015 Link to this post

    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.
  14. Lagrange
    Lagrange avatar
    16 posts
    Member since:
    Sep 2010

    Posted 12 Oct 2015 in reply to Simeon Simeonov Link to this post

    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

  15. Simeon Simeonov
    Admin
    Simeon Simeonov avatar
    24 posts

    Posted 13 Oct 2015 Link to this post

    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.
Back to Top
DevCraft banner