I found this snippet here:
public static T DeepClone<T>(this T obj)
{
using (var ms = new MemoryStream()) {
var bf = new BinaryFormatter();
bf.Serialize(ms, obj);
ms.Position = 0;
return (T)bf.Deserialize(ms);
}
}
Which says that we can do deep copy of all related objects through this thing.
I'm trying to do a copy like this:
db.Detach(myEntity);
myEntity.EntityKEy = null;
Entity newEntity = new Entity();
newEntity = DeepClone<Entity>(Entity);
db.Entities.AddObject(newEntity);
db.SaveChanges();
IT works, but still does not copy any nested\related records. what do I do wrong here?
I have this structure Entity->ChildEntity ->ChildChildEntity
-> - one-to-many
so I assume when I copy entity it will also copy all child records.
UPDATE: After suggestions, I did this:
Entity newEntity = new Entity();
Eneity Entity = db.Include("ChildEntity").Where(p=>p.Id==Id).Single();
newEntity = DeepClone<Entity>(Entity);
db.Detach(myEntity);
myEntity.EntityKEy = null;
db.Entities.AddObject(newEntity);
db.SaveChanges();
Getting exception on AddObject line:
An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.
To copy/paste an entity: Select the entity. Right-click the entity and click Copy.
clone() is indeed a shallow copy. However, it's designed to throw a CloneNotSupportedException unless your object implements Cloneable . And when you implement Cloneable , you should override clone() to make it do a deep copy, by calling clone() on all fields that are themselves cloneable.
A cloned entity is an exact copy of an entity, which means that the Transform and all other components with their set values are copied too.
The important point is that you must load related entities and create deep clone prior to detaching. If you detach the entity all relations are silently removed because Detach
method works only for single entity and entity graph cannot consists of both attached and detached entities. That is a reason why you need serialization instead of simply calling Detach
.
Don't forget to turn off lazy loading otherwise your serialization will pull data for other navigation properties from database as well. Also remember that this deep copy will create new version of all entities in the graph so adding the root entity will add all related entities as well.
The EntityKeys for all the child objects get cloned too, so you need to set each child's EntityKey to null before trying to add them with AddObject.
Entity oldEntity = db.Include("ChildEntity").Where(p => p.Id == Id).Single();
Entity newEntity = oldEntity.DeepClone(); // assuming you've put your DeepClone extension method in a static class so that it can be used as an extension
newEntity.EntityKey = null;
foreach(var childEntity in newEntity.ChildEntities)
{
childEntity.EntityKey = null;
}
db.Entities.AddObject(newEntity);
db.SaveChanges();
If you haven't loaded the child entities before detaching the entity, they will not be serialized. Make sure all those navigational properties you want to deep clone are loaded before you detach the entity.
Edit
Eager load the navigational properties that must be serialized
var entity = db.Entities.Include("ChildEntity.ChildChildEntity")
.Where(l=>l.ID == myId).Single();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With