entity framework5实体的深度复制/克隆
我正在使用entity framework5( DBContext
),我试图find最佳的方法来深入复制实体(即复制实体和所有相关的对象),然后将新的实体保存在数据库中。 我该怎么做? 我已经研究过使用扩展方法,如CloneHelper
但我不知道它是否适用于DBContext
。
克隆一个实体的一个便宜的简单方法是做这样的事情:
var originalEntity = Context.MySet.AsNoTracking() .FirstOrDefault(e => e.Id == 1); Context.MySet.Add(originalEntity); Context.SaveChanges();
这里的诀窍是AsNoTracking() – 当你加载这样一个实体时,你的上下文不知道它,当你调用SaveChanges时,它会把它当作一个新的实体。
如果MySet
具有对MyProperty
的引用,并且您也需要它的副本,则只需使用Include
:
var originalEntity = Context.MySet.Include("MyProperty") .AsNoTracking() .FirstOrDefault(e => e.Id == 1);
这是另一种select。
在某些情况下,我更喜欢它,因为它不需要专门运行查询来获取数据以进行克隆。 您可以使用此方法创build您已从数据库中获取的实体的克隆。
//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();
此方法将当前值从源复制到已添加的新行。
这是允许通用克隆的通用扩展方法。
您必须从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(); }