I am using Entity Framework 5 (DBContext
) and I am trying to find the best way to deep copy an entity (i.e. copy the entity and all related objects) and then save the new entities in the database. How can I do this? I have looked into using extension methods such as CloneHelper
but I am not sure if it applies to DBContext
.
-
I tried to Deep clone/duplicate the Entity objects using reflection described at the following [link](http://code.msdn.microsoft.com/CSEFDeepCloneObject-12a5cb95) but as I understand it, EntityObject derived types are not supported by the DbContext API – kypk Mar 10 '13 at 08:23
4 Answers
One cheap easy way of cloning an entity is to do something like this:
var originalEntity = Context.MySet.AsNoTracking()
.FirstOrDefault(e => e.Id == 1);
Context.MySet.Add(originalEntity);
Context.SaveChanges();
the trick here is AsNoTracking() - when you load an entity like this, your context do not know about it and when you call SaveChanges, it will treat it like a new entity.
If MySet
has a reference to MyProperty
and you want a copy of it too, just use an Include
:
var originalEntity = Context.MySet.Include("MyProperty")
.AsNoTracking()
.FirstOrDefault(e => e.Id == 1);

- 9,338
- 5
- 44
- 79

- 7,379
- 6
- 28
- 44
-
This trick just safed me quite some time :-). But with my configuration of DbContext there was an exception about not beeing able to automatically add the Entity. I had to go over the ObjectContext like this `DirectCast(DbContext, IObjectContextAdapter).ObjectContext.AddObject(entitySetName, entity)` – Patrick Jun 26 '13 at 09:36
-
I have projection from ef context like this `dbContext,Select(x=> { a = x, ab = x.MyCollection.Where(g=>g.Id>2)}).ToList()` If i add `AsNoTracking()` There is data loss from the query. – Eldho Feb 08 '16 at 12:39
-
8This worked great for me using EF Core. However I had to set my primary keys on the parent and the nested objects to Guid.Empty to prevent EF trying to insert duplicate rows in the database. If you use integer keys I suspect setting them to 0 would have the same effect. – agileMike Jul 26 '17 at 22:56
-
1Good to know : you can include nested elements with the dot operator such as : `.Include("MyProperty.MyNestedObjet")` , see https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k(System.Data.Entity.Infrastructure.DbQuery%601.Include);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5);k(DevLang-csharp)&rd=true – Malick Jul 29 '17 at 07:24
-
1When I copy the nested entities, do I have to iterate through them and give them all new `Guid` Id's? – Train Jan 27 '20 at 18:35
-
1
Here's another option.
I prefer it in some cases because it does not require you to run a query specifically to get data to be cloned. You can use this method to create clones of entities you've already obtained from the database.
//Get entity to be cloned
var source = Context.ExampleRows.FirstOrDefault();
//Create and add clone object to context before setting its values
var clone = new ExampleRow();
Context.ExampleRows.Add(clone);
//Copy values from source to clone
var sourceValues = Context.Entry(source).CurrentValues;
Context.Entry(clone).CurrentValues.SetValues(sourceValues);
//Change values of the copied entity
clone.ExampleProperty = "New Value";
//Insert clone with changes into database
Context.SaveChanges();
This method copies the current values from the source to a new row that has been added.

- 10,908
- 12
- 46
- 58

- 804
- 10
- 12
-
2This works great if you want the clone to be inserted together with updates of the original in one SaveChanges – Dacker Jan 29 '16 at 17:19
-
1`SetValues` doesn't work if the new object isn't attached to the context. It throws an `InvalidOperationException` exception. If all you want to do is clone the entity in a detached state, you can add the entity to the context, set its current values, then detach it. – Suncat2000 Dec 28 '16 at 18:25
-
8This is not a **deep** clone. The question title and text ask about a deep clone to "copy the entity and all related objects". – Zach Mierzejewski Apr 30 '18 at 21:27
This is a generic extension method which allows generic cloning.
You have to fetch System.Linq.Dynamic
from nuget.
public TEntity Clone<TEntity>(this DbContext context, TEntity entity) where TEntity : class
{
var keyName = GetKeyName<TEntity>();
var keyValue = context.Entry(entity).Property(keyName).CurrentValue;
var keyType = typeof(TEntity).GetProperty(keyName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance).PropertyType;
var dbSet = context.Set<TEntity>();
var newEntity = dbSet
.Where(keyName + " = @0", keyValue)
.AsNoTracking()
.Single();
context.Entry(newEntity).Property(keyName).CurrentValue = keyType.GetDefault();
context.Add(newEntity);
return newEntity;
}
The only thing you have to implement yourself is the GetKeyName method. This could be anything from return typeof(TEntity).Name + "Id"
to return the first guid property
or return the first property marked with DatabaseGenerated(DatabaseGeneratedOption.Identity)]
.
In my case I already marked my classes with [DataServiceKeyAttribute("EntityId")]
private string GetKeyName<TEntity>() where TEntity : class
{
return ((DataServiceKeyAttribute)typeof(TEntity)
.GetCustomAttributes(typeof(DataServiceKeyAttribute), true).First())
.KeyNames.Single();
}

- 30,746
- 24
- 119
- 189
I had the same issue in Entity Framework Core where deep clone involves multiple steps when children entities are lazy loaded. One way to clone the whole structure is the following:
var clonedItem = Context.Parent.AsNoTracking()
.Include(u => u.Child1)
.Include(u => u.Child2)
// deep includes might go here (see ThenInclude)
.FirstOrDefault(u => u.ParentId == parentId);
// remove old id from parent
clonedItem.ParentId = 0;
// remove old ids from children
clonedItem.Parent1.ForEach(x =>
{
x.Child1Id = 0;
x.ParentId= 0;
});
clonedItem.Parent2.ForEach(x =>
{
x.Child2Id = 0;
x.ParentId= 0;
});
// customize entities before inserting it
// mark everything for insert
Context.Parent.Add(clonedItem);
// save everything in one single transaction
Context.SaveChanges();
Of course, there are ways to make generic functions to eager load everything and/or reset values for all keys, but this should make all the steps much clear and customizable (e.g. all for some children to not be cloned at all, by skipping their Include).

- 22,016
- 16
- 145
- 164