我正在使用Entity Framework5 (DBContext
),我正在尝试找到深度复制实体的最佳方法(即复制实体和所有相关对象),然后将新实体保存在数据库中。我该怎么做呢?我曾研究过使用CloneHelper
等扩展方法,但我不确定它是否适用于DBContext
。
发布于 2014-02-12 21:41:41
这里有另一个选择。
在某些情况下,我更喜欢它,因为它不需要您专门运行查询来获得要克隆的数据。您可以使用此方法创建已从数据库中获得的实体的克隆。
//Get entity to be cloned
var source = Context.ExampleRows.FirstOrDefault();
//Create and add clone object to context before setting its values
var clone = new ExampleRow();
Context.ExampleRows.Add(clone);
//Copy values from source to clone
var sourceValues = Context.Entry(source).CurrentValues;
Context.Entry(clone).CurrentValues.SetValues(sourceValues);
//Change values of the copied entity
clone.ExampleProperty = "New Value";
//Insert clone with changes into database
Context.SaveChanges();
此方法将当前值从源复制到已添加的新行。
发布于 2015-10-27 15:01:36
这是一个允许泛型克隆的泛型扩展方法。
您必须从nuget获取System.Linq.Dynamic
。
public TEntity Clone<TEntity>(this DbContext context, TEntity entity) where TEntity : class
{
var keyName = GetKeyName<TEntity>();
var keyValue = context.Entry(entity).Property(keyName).CurrentValue;
var keyType = typeof(TEntity).GetProperty(keyName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance).PropertyType;
var dbSet = context.Set<TEntity>();
var newEntity = dbSet
.Where(keyName + " = @0", keyValue)
.AsNoTracking()
.Single();
context.Entry(newEntity).Property(keyName).CurrentValue = keyType.GetDefault();
context.Add(newEntity);
return newEntity;
}
您唯一需要自己实现的就是GetKeyName方法。这可以是从return typeof(TEntity).Name + "Id"
到return the first guid property
的任何内容,也可以返回标记为DatabaseGenerated(DatabaseGeneratedOption.Identity)]
的第一个属性。
在我的例子中,我已经用[DataServiceKeyAttribute("EntityId")]
标记了类
private string GetKeyName<TEntity>() where TEntity : class
{
return ((DataServiceKeyAttribute)typeof(TEntity)
.GetCustomAttributes(typeof(DataServiceKeyAttribute), true).First())
.KeyNames.Single();
}
发布于 2019-02-04 16:23:29
我在Entity Framework Core中遇到了同样的问题,当子实体被延迟加载时,深度克隆涉及多个步骤。克隆整个结构的一种方法如下:
var clonedItem = Context.Parent.AsNoTracking()
.Include(u => u.Child1)
.Include(u => u.Child2)
// deep includes might go here (see ThenInclude)
.FirstOrDefault(u => u.ParentId == parentId);
// remove old id from parent
clonedItem.ParentId = 0;
// remove old ids from children
clonedItem.Parent1.ForEach(x =>
{
x.Child1Id = 0;
x.ParentId= 0;
});
clonedItem.Parent2.ForEach(x =>
{
x.Child2Id = 0;
x.ParentId= 0;
});
// customize entities before inserting it
// mark everything for insert
Context.Parent.Add(clonedItem);
// save everything in one single transaction
Context.SaveChanges();
当然,有一些方法可以让泛型函数急于加载所有内容和/或重置所有键的值,但这应该使所有步骤变得非常清晰和可定制(例如,对于某些子项,通过跳过它们的包含,所有步骤都不被克隆)。
https://stackoverflow.com/questions/15308747
复制相似问题