Entity Framework cloning

On a recent project, I had come across the need to copy an existing EF Entity.  Upon my research, I found several ways to accomplish this task.  One way is to create a new object and manually assign the property values using the existing object values.  You can also use some kind of mapping utility if it supports deep copying.  However, I will demonstrate two alternative ways to clone an Entity object using EF techniques.

Disable EF Tracking

When you are retrieving an entity or entities from a dataset, you can tell Entity Framework not to track any of the changes that you are making to that object and then add that entity as a new entity to the dataset.  With using .AsNoTracking, the context doesn’t know anything about the existing entity.

var entity = context.MyDataSet
                    .AsNoTracking()
                    .FirstOrDefault(e => e.Id == 1);

context.MyDataSet.Add(entity);
context.SaveChanges();  

You can also include child entities as well

var entity = context.MyDataSet
                    .AsNoTracking()
                    .Including(ds => ds.MyChildEntities)
                    .FirstOrDefault(e => e.Id == 1);
context.MyDataSet.Add(entity);
context.SaveChanges();  // creates a new object graph in the database

EF Copying Current Values

Using this technique, you can get the current values from an existing entity object and set the values to your newly created entity object.

var originalEntity = context.MyDataSet
                            .FirstOrDefault(e => e.Id == 1);

var entity = new MyDataSetEntity();
context.MyDataSet.Add(entity);  //Create and add new entity object to context before setting its values

var originalEntityValues = Context.Entry(originalEntity).CurrentValues;
Context.Entry(entity).CurrentValues.SetValues(originalEntityValues);  //Copy values from original entity to new entity

entity.MyProperty1 = "Changed value"; // make any changes to the new entity
entity.MyProperty2 = "Another changed value";

context.SaveChanges();  


Comments

  1. Tareq Alkatout says:

    Many Thanks that’s work for me ,,
    I think best method to cloning Entities in EF is Copy Values

  2. Hi,
    any idea about child’s child elements? In other words if a child element has it self a child element how we can copy recursively the whole tree?
    Thank you in advance
    Pino

  3. Many thanks, that´s work for me too.
    i spend lot of time looking for something like that.

  4. Disable EF Tracking worked very well in EF6 for me.

    But, to make it work, I had to:

    + change the “.Including(..” to “.Include(”
    + using System.Data.Entity;

    to satisfy the compiler.

    Changing values before SaveChanges() also works.

    Thank you so much.

  5. Chad Holmes says:

    AsNoTracking() That one little function was the key to unlocking hours of frustration. I needed to retain a massive file upload column in the entity, while allowing a replacement upload if, and only if desired. Couldn’t get EF to copy the values without throwing exception…until now. THANKS!

  6. Many thanks! This is excellent and saved me a lot of time. I’m still fairly new to EF and had a class with two child collections I needed to clone, I can’t believe how easy it was!

  7. You are a saviour Lori! Was looking for a fast ef based solution for an entire month.
    Thankyou!

    • You’re welcome!

      • I recently found a issue in cloning the way described.
        With AsNoTracking() approach, EF will create a new proxy as well for the new entity and there is already an existing proxy for original entity. Thus, there are 2 proxies existing now.
        Then, as EF copies properties, it will copy every property whether or not marked with NotMappedAttribute. This will lead to copy a reference to the entity wrapper as well (which is present in original entity).
        Thus, now there are two proxies with reference to the same wrapper instance.
        Now, if you execute statement below:
        …..this.context.Entry(originalEntity).CurrentValues.SetValues(entityCloned)…

        an error will be thrown as “The entity wrapper stored in the proxy does not reference the same proxy.”

        Thus, with above approaches it become a problem.
        I figured out that if I can avoid copying reference to the wrapper, this may work.

        What do you think on this issue? Any suggestions to figure it out.
        Please mail @mentioned id.
        Thank you!

  8. Jeethendra says:

    Fantastic post. I just got rid of 50 lines of code by using the first approach “Disabling tracking”. Appreciate your effort for sharing the knowledge.

  9. Sylvain Provencher says:

    Thanks. This article is what I’am looking for.

  10. David Engel says:

    The AsNoTracking method did not work for me initially. I was able to get it working by setting the Id for the retrieved entity to 0 prior to Adding back to the db context. When trying to Add the new entity with the Id still specified as the original Id, I was receiving an error on Add.

Speak Your Mind

*