Entity Framework Object Copy

c# entity-framework

Question

I want to create a clone of my EF4.1 class X along with all of its offspring records. X.Y., X.Y.Z.

If I perform the following, an error is returned.

The object's key information includes the property "X.ID," which cannot be changed.

public void CopyX(long ID)
{
    var c = db.Xs.Include("Y").Include("W").Include("Y.Z").SingleOrDefault(x => x.ID == ID);
    if (c != null)
    {
        c.ID = 0;
        c.Title = "Copy Of " + c.Title;
        for (var m = 0; m < c.Ys.Count; m++)
        {
            c.Ys[m].ID = 0;
            c.Ys[m].XID=0-m;
            for (var p = 0; p < c.Ys[m].Zs.Count; p++)
            {
                c.Ys[m].Zs[p].XID = 0 - m;
                c.Ys[m].Zs[p].ID = 0 - p;
            }
        }
        for (var i = 0; i < c.Ws.Count; i++)
        {
            c.Ws[i].ID = 0 - i;
            c.Ws[i].XID = 0;
        }
        db.Entry<Content>(c).State = System.Data.EntityState.Added;
        db.SaveChanges();
    }
}

Is there another method to duplicate entity objects?

NOTE: Each W, X, Y, and Z has many characteristics.

1
13
8/24/2011 8:45:39 AM

Accepted Answer

The easiest technique to create an accurate deep duplicate of the whole entity graph is to deserialize the original entity graph from a memory stream into a new instance. Your entity has to support serialization. It is used often with DataContractSerializer, although binary serialization is also an option.

9
8/24/2011 8:53:43 AM

Popular Answer

With the DbExtensions.AsNotracking(), this is absurdly simple in entity-framework-5.

Returns a new query where the entities returned will not be cached in the DbContext or ObjectContext.

All objects in the object graph seem to be like this.

Simply grasp your graph and what you want and don't want copied or stored into the database.

Assume we have the following objects:

public class Person
{
  public int ID { get; set; }
  public string Name { get; set; }
  public virtual ICollection<Address> Addresses { get; set; }
}

public class Address
{
  public int ID { get; set; }
  public AddressLine { get; set; }
  public int StateID { get; set; }

  public ICollection<State> { get; set; }
}

Consequently, I must duplicate the addresses in order to duplicate a person, but I don't want to repeat the states.

var person = this._context.Persons
  .Include(i => i.Addresses)
  .AsNoTracking()
  .First();

// if this is a Guid, just do Guid.NewGuid();
// setting IDs to zero(0) assume the database is using an Identity Column
person.ID = 0;

foreach (var address in person.Addresses)
{
  address.ID = 0;
}

this._context.Persons.Add(person);
this._context.SaveChanges();

If you later wanted to insert a third copy using the same objects, you could either perform the query once again (with AsNoTracking()) or remove the objects (example):

dbContext.Entry(person).State = EntityState.Detached;
person.ID = 0;
foreach (var address in person.Addresses)
{
  dbContext.Entry(address).State = EntityState.Detached;
  address.ID = 0;
}

this._context.Persons.Add(person);
this._context.SaveChanges();


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow