我正在创建软件,用户可以根据旧产品创建新产品。
现在我需要使用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复制属性。
答案 0 :(得分:65)
要在实体框架中克隆实体,您只需从DataContext
分离实体,然后将其重新添加到EntityCollection
。
context.Detach(entity);
entityCollection.Add(entity);
更新(来自评论)
context.Entry(entity).State = EntityState.Detached;
entity.id = 0;
entity.property = value;
context.Entry(entity).State = EntityState.Added;
context.SaveChanges();
答案 1 :(得分:15)
使用直接序列化,您可以这样做:
使用Reflection,但有更多代码可以执行此操作: http://msmvps.com/blogs/matthieu/archive/2008/05/31/entity-cloner.aspx
答案 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)
要添加内容基于现有行的新行,请按以下步骤操作:
以下是一个例子:
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