11

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?

2 Answers 2

8

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.