复制实体框架对象

Anu*_*dey 13 c# entity-framework

我有一个EF4.1类X,我想复制它以及它的所有子记录.XY和XYZ

现在,如果我执行以下操作,则返回错误.

属性"X.ID"是对象的关键信息的一部分,无法修改.

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

或者是否有其他方式来制作实体对象的副本.

注意:每个W,X,Y,Z都有多个属性.

Eri*_*ips 27

,使用DbExtensions.AsNotracking()非常容易.

返回一个新查询,其中返回的实体不会缓存在DbContext或ObjectContext中.

这似乎是对象图中所有对象的情况.

您只需要真正了解您的图表以及您不希望将数据插入/复制到数据库中.

让我们假设我们有像这样的对象:

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; }
}
Run Code Online (Sandbox Code Playgroud)

所以为了复制一个人,我需要复制地址,但我不想复制状态.

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();
Run Code Online (Sandbox Code Playgroud)

如果您希望再次重复使用这些相同的对象来插入第三个副本,则可以再次运行查询(使用AsNoTracking())或分离对象(示例):

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();
Run Code Online (Sandbox Code Playgroud)

  • 太好了,谢谢分享.值得一提的是,AsNoTracking()使得从DB加载对象的速度更快.如果DB对象(GET)不需要更改,则非常有用. (3认同)

Lad*_*nka 9

您需要对整个实体图进行正确的深层复制 - 最好的方法是将原始实体图序列化为内存流并将其反序列化为新实例.您的实体必须是可序列化的.它通常与DataContractSerializer一起使用,但您也可以使用二进制序列化.