我正在尝试使用SetValues方法克隆实体,但是我收到以下错误:
无法跟踪实体类型'TariffPeriod'的实例,因为已经跟踪了另一个具有{'Id'}键值的实例。附加现有实体时,请确保只附加一个具有给定键值的实体实例。
以下是代码:
var period2 = _tariffRepository.GetPeriodFull(period.GUID);
var period3 = new TariffPeriod();
_appDbContext.TariffPeriods.Add(period3);
_appDbContext.Entry(period3).CurrentValues.SetValues(period2);
我看到错误是由于主键的值被复制到新实体中。那么,如何在没有密钥的情况下复制值?
感谢您的帮助 埃里克
答案 0 :(得分:5)
您可以尝试获取period2数据的克隆并在分配到period3之前修改Id
var values = db.Entry(period2).CurrentValues.Clone();
values["Id"] = 0;
db.Entry(period3).CurrentValues.SetValues(values);
答案 1 :(得分:3)
这是我的解决方案,它基于@ grek40的解决方案,并添加了强制类型转换功能以避免字符串文字并允许将来进行重构。
_appDbContext
辅助方法:
public TEntity DetachedClone<TEntity>(TEntity entity) where TEntity : class
=> Entry(entity).CurrentValues.Clone().ToObject() as TEntity;
您的答案:
var period2 = _tariffRepository.GetPeriodFull(period.GUID);
var period3 = _appDbContext.DetachedClone(period2);
_appDbContext.TariffPeriods.Add(period3);
您也可以使用简单的JSON深度克隆功能。像魅力一样工作。我更喜欢这种方法,因为第一种解决方案是先使用.Entry()
附加条目,这可能是不希望的
public static T Clone<T>(T source)
{
var serialized = JsonConvert.SerializeObject(source);
return JsonConvert.DeserializeObject<T>(serialized);
}
(ノ◕ヮ◕)ノ ✲゚ 。⋆
答案 2 :(得分:2)
将值从旧时段复制到新时段,然后使用唯一值(在本例中为主键)设置属性,最后将实体添加到DbContext。
var period2 = _tariffRepository.GetPeriodFull(period.GUID);
var period3 = new TariffPeriod();
_appDbContext.Entry(period3).CurrentValues.SetValues(period2);
period3.Id = 0;
_appDbContext.TariffPeriods.Add(period3);