我在使用实体框架更新被跟踪的实体时遇到问题.我正在使用DotNet 6. 假设我有一个SnapshotEntity和一个UpdateSnapshotDto. 更新快照Dto它被用作‘输入’,它从前端获取字段.我使用AutoMapper将UpdateSnapshotDto转换为SnapshotEntity. 我try 过的最简单的方法(失败了)是这样的:
var oldSnapshot = await snapshotRepository.GetSingleOrDefaultAsync(e => e.Id == request.snapshot.Id);
var newSnapshot = mapper.Map<SnapshotEntity>(request.snapshot);
oldSnapshot = newSnapshot;
await snapshotRepository.SaveChangesAsync();
但当然不起作用,因为当我指定oldSnapshot=newSnapshot时,它可能会丢失跟踪.
所以我想我可以从输入中更新,就像这样:
var newSnapshot = mapper.Map<SnapshotEntity>(request.snapshot);
snapshotRepository.Update(newSnapshot);
但是这种方法对我来说不起作用,因为如果我像这样进行暴力更新,我会丢失一些保存在原始快照中的东西(例如,在DB中,旧快照有一个CreatedDate和列,这些列不会在UpdateSnapshotDto中传递).
所以我想读取文件,赋值,然后像这样更新:
var oldSnapshot = await snapshotRepository.GetSingleOrDefaultAsync(e => e.Id == request.snapshot.Id);
var newSnapshot = mapper.Map<SnapshotEntity>(request.snapshot);
newSnapshot.CreatedDate = oldSnapshot.CreatedDate;
newSnapshot.CreatedBy = oldSnapshot.CreatedBy;
snapshotRepository.Update(newSnapshot);
但这两种方法都不起作用,因为oldSnapshot是被跟踪的,当我try 执行更新方法时,它告诉我它已经被跟踪了.
我找到了两个解决方案,但我不想使用它们:
- 第一个解决方案是我逐个字段为oldSnapshot赋值,例如oldSnapshot.Name=newSnaphot.Name等,但实际上我会避免使用这种方法,因为如果快照会增加属性,这个逻辑将不再起作用,需要修复;
- 第二个解决方案是,我使用我所描述的第三种try ,但是使用AsNoTrack()读取实体,并且我希望避免在项目中引入AsNoTrack()逻辑.
有什么主意吗?另一种解决方案可能是使用反射在旧的跟踪实体上分配所有新的实体,但我不知道如何做到这一点,对于简单的更新来说,它可能太高了.