Reputation: 1695
Having 2 separate databases with the same schema, I need to copy entities (records) from one database to another using Entity Framework 4.
I'm creating 2 Contexts, but I'm getting the following error when I add one entity to the second Context:
An entity object cannot be referenced by multiple instances of IEntityChangeTracker.
I know I can avoid that error if i use the Detach method, but in that case the related entities are lost!
Sample code:
var cx = new MyEntities();
//eager load related tables
var allEntities = from x in cx.Reservation.Include("Detail.MoreDetail")
select x;
// new instance of context but connected to a second database
var cx2 = new MyEntities( new ConnectionString...);
foreach (var e in allEntities)
{
//cx.Detach(reservation); // can't detach, or related entities will be lost
cx2.AddToReservation(reservation); // error happens here!
cx2.SaveChanges();
}
How can I perform such operation? Alternatively, how can I detach the entity without losing the related entities?
Upvotes: 10
Views: 12544
Reputation: 68902
A good solution which can save time: http://lorifpeterson.com/?p=75
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();
Upvotes: 1
Reputation: 1695
For future reference, the following article helped me:
Cloning the Entity object and all related children using the Entity Framework
Upvotes: 6
Reputation: 83358
For once the error message is helpful - entities can only belong to one context at a time. To do what you're wanting you'll need to Detatch
each entity from the first context before adding it to the second.
Like you said, this will kill related entities. Unfortunately you'll have to deal with this (annoying) aspect of Detach
.
Upvotes: 8