在entity framework上克隆数据
我正在创build软件,用户可以根据旧产品创build新产品。
现在我需要使用Entity Framework进行复制/克隆操作。 首先,我开始写这样的:
foreach(表1中的sourcedata1) { ...创build新表 ...复制数据 ...创buildGuid ...补充 foreach(表2中的sourcedata2) { ...创build新表 ...复制数据 ...创buildGuid ...补充 ... 等等 } }
问题是这不是一个好办法。 是否有任何简单的方法克隆信息(除了需要为新行生成的Guid)或者我应该手动复制一切?
其他解决scheme
您也可以使用EmitMapper或AutoMapper来复制属性。
使用直接序列化,你可以这样做:
使用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; }
这是我写的一个简单的方法。 它应该为大多数人工作。
要添加其内容基于现有行的新行,请按照下列步骤操作:
- 获取基于起始行的实体。
- 将实体的input状态设置为已添加。
- 修改实体。
- 保存更改。
这是一个例子:
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