在entity framework上克隆数据

我正在创build软件,用户可以根据旧产品创build新产品。

现在我需要使用Entity Framework进行复制/克隆操作。 首先,我开始写这样的:

 foreach(表1中的sourcedata1)
 {
    ...创build新表
    ...复制数据
    ...创buildGuid
    ...补充
    foreach(表2中的sourcedata2)
    {
        ...创build新表
        ...复制数据
        ...创buildGuid
        ...补充       

        ... 等等
    }
 }

问题是这不是一个好办法。 是否有任何简单的方法克隆信息(除了需要为新行生成的Guid)或者我应该手动复制一切?

其他解决scheme

您也可以使用EmitMapper或AutoMapper来复制属性。

使用直接序列化,你可以这样做:

http://social.msdn.microsoft.com/forums/en-US/adodotnetentityframework/thread/a967b44b-c85c-4afd-a499-f6ff604e2139/

使用reflection,但有更多的代码,你可以做到这一点: http : //msmvps.com/blogs/matthieu/archive/2008/05/31/entity-cloner.aspx

要在entity framework中克隆实体,您可以简单地从DataContext分离实体,然后将其重新添加到EntityCollection

 context.Detach(entity); entityCollection.Add(entity); 

EF6 + 更新 (来自评论)

 context.Entry(entity).State = EntityState.Detached; entity.id = 0; entity.property = value; context.Entry(entity).State = EntityState.Added; context.SaveChanges(); 
 public static EntityObject Clone(this EntityObject Entity) { var Type = Entity.GetType(); var Clone = Activator.CreateInstance(Type); foreach (var Property in Type.GetProperties(BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.SetProperty)) { if (Property.PropertyType.IsGenericType && Property.PropertyType.GetGenericTypeDefinition() == typeof(EntityReference<>)) continue; if (Property.PropertyType.IsGenericType && Property.PropertyType.GetGenericTypeDefinition() == typeof(EntityCollection<>)) continue; if (Property.PropertyType.IsSubclassOf(typeof(EntityObject))) continue; if (Property.CanWrite) { Property.SetValue(Clone, Property.GetValue(Entity, null), null); } } return (EntityObject)Clone; } 

这是我写的一个简单的方法。 它应该为大多数人工作。

要添加其内容基于现有行的新行,请按照下列步骤操作:

  1. 获取基于起始行的实体。
  2. 将实体的input状态设置为已添加。
  3. 修改实体。
  4. 保存更改。

这是一个例子:

 var rabbit = db.Rabbits.First(r => r.Name == "Hopper"); db.Entry(rabbit).State = EntityState.Added; rabbit.IsFlop = false; db.SaveChanges(); 

如果要在代码执行中稍后创build实体的副本以供比较,则可以在新的数据库上下文中select该实体。

例如,如果你正在更新一个实体,那么在后面的代码中你要比较更新的和原始的实体:

 var db = new dbEntityContext(); var dbOrig = new dbEntityContext(); var myEntity = db.tblData.FirstOrDefault(t => t.Id == 123); var myEntityOrig = dbOrig.tblData.FirstOrDefault(t => t.Id == 123); //Update the entity with changes myEntity.FirstName = "Gary"; //Save Changes db.SaveChnages(); 

此时, myEntity.FirstName将包含"Gary"myEntityOrig.FirstName将包含原始值。 如果你有一个function来logging你可以传入更新和原始实体的更改。

使用generics复制实体的一个非常简短的方法(VB,抱歉)。
它复制外键值(外部标识),但不加载其相关对象。

 <Extension> _ Public Function DuplicateEntity(Of T As {New, Class})(ctx As myContext, ent As T) As T Dim other As New T 'T is a proxy type, but New T creates a non proxy instance ctx.Entry(other).State = EntityState.Added 'attaches it to ctx ctx.Entry(other).CurrentValues.SetValues(ent) 'copies primitive properties Return other End Function 

例如:

 newDad = ctx.DuplicateEntity(oDad) newDad.RIDGrandpa ' int value copied newDad.Grandpa ' object for RIDGrandpa above, equals Nothing(null) newDad.Children ' nothing, empty 

在这种情况下,我不知道如何重新加载Grandpa
这不起作用:

 ctx.SaveChanges() ctx.Entry(newDad).Reload() 

但真的没问题 如果我需要的话,我宁愿用手指派Grandpa

 newDad.Grandpa = oDad.Grandpa 

编辑:正如马特W在他的评论build议 ,分离和find新的实体,你得到它的孩子加载(而不是集合)。

 ctx.Entry(newDad).State = EntityState.Detached ctx.Find(newDad.RowId) 'you have to know the key name