克隆实体框架的数据

时间:2010-02-02 15:24:41

标签: entity-framework

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

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

foreach(sourcedata1 in table1)
{
   ... create new table
   ... copy data
   ... create Guid
   ... add
   foreach(sourcedata2 in table2)
   {
       ... create new table
       ... copy data
       ... create Guid
       ... add       

       ... and so on
   }
}

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

其他解决方案

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

6 个答案:

答案 0 :(得分:65)

要在实体框架中克隆实体,您只需从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();

答案 1 :(得分:15)

答案 2 :(得分:10)

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;
}

这是我写的一个简单方法。它适用于大多数人。

答案 3 :(得分:8)

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

  1. 根据起始行获取实体。
  2. 将实体的条目状态设置为“添加”。
  3. 修改实体。
  4. 保存更改。
  5. 以下是一个例子:

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

答案 4 :(得分:0)

如果要在代码执行后期创建实体的副本以进行比较,可以在新的db上下文中选择实体。

例如,如果您要更新实体,那么稍后您要在代码中比较更新的原始实体:

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将包含原始值。如果您具有记录更改的功能,则可以在传递更新的原始实体的地方使用。

答案 5 :(得分:0)

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

<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

修改 作为MattW proposes in his comment,分离并找到新实体,您可以加载其子代(而不是集合)。

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