如何在 Entity Framework Core 中克隆实体?

问题描述 投票:0回答:4

我尝试使用 SetValues 方法克隆实体,但出现以下错误:

无法跟踪实体类型“TariffPeriod”的实例,因为已跟踪具有相同键值 {'Id'} 的另一个实例。附加现有实体时,请确保仅附加一个具有给定键值的实体实例。

这是代码:

var period2 = _tariffRepository.GetPeriodFull(period.GUID);
var period3 = new TariffPeriod();
_appDbContext.TariffPeriods.Add(period3);
_appDbContext.Entry(period3).CurrentValues.SetValues(period2);

我看到错误是由于主键的值被复制到新实体中造成的。那么,如何在没有密钥的情况下复制值呢?

感谢您的帮助 埃里克

entity-framework
4个回答
18
投票

您可以尝试获取 period2 数据的克隆并在分配给 period3 之前修改 Id

var values = db.Entry(period2).CurrentValues.Clone();
values["Id"] = 0;
db.Entry(period3).CurrentValues.SetValues(values);

16
投票

解决方案1

这是我的解决方案,基于 @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);

解决方案2

您也可以使用简单的 JSON 深度克隆功能。就像魅力一样起作用。我更喜欢这种方法,因为第一个解决方案涉及首先使用

.Entry()
附加条目,这可能是不可取的

    public static T Clone<T>(T source)
    {
        var serialized = JsonConvert.SerializeObject(source);
        return JsonConvert.DeserializeObject<T>(serialized);
    }

(ノ◕ヮ◕)ノ✲゚。⋆


6
投票

将旧周期的值复制到新周期,然后设置具有唯一值的属性(在本例中为主键),最后将实体添加到 DbContext。

var period2 = _tariffRepository.GetPeriodFull(period.GUID);
var period3 = new TariffPeriod();
_appDbContext.Entry(period3).CurrentValues.SetValues(period2);
period3.Id = 0;
_appDbContext.TariffPeriods.Add(period3);

0
投票

在 EF Core 8 中,我只是使用

AsNoTracking
获取实体,将其 Id 设置为 0 并再次插入它

var myEntity = await _dbContext.MyEntities
    .AsNoTracking()
    .SingleOrDefaultAsync(e => e.EventStart.Date == DateTime.UtcNow.Date);

myEntity.Id = 0;

await _dbContext.MyEntities.AddAsync(myEntity);
await _dbContext.SaveChangesAsync();
© www.soinside.com 2019 - 2024. All rights reserved.