【发布时间】:2019-05-21 07:45:20
【问题描述】:
我在在 EF Core 中更新实体时遇到问题,然后在表中记录这些更改。使用的技术有:
- .NET Core 2.2.0
- EF Core 2.2.3
所以,我想从数据库中获取一个实体,在前端对其进行编辑,然后在后端对其进行更新,并将这些更改保存到数据库中。最重要的是,我有一个名为 ChangeLogs 的表,其中最重要的字段是 From(映射自 OldValues)和 To(映射自 CurrentValues)。好吧,这两个字段是相同的(意味着它们具有完全相同的值,即新值),情况如下:
-
我像这样从数据库中获取实体
_context.Anomalies .Include(a => a.Asset) .FirstOrDefaultAsync(a => a.Id == anomalyId) 在前端编辑实体,然后发出PUT请求来更新它;
-
更新实体:
为了让
Update()工作,首先我必须调用它:_context.DetachAllEntities();否则我会收到一条错误消息,指出已在跟踪具有相同 ID 的实体。然后拨打Update()和SaveChanges():_context.Anomalies.Update(anomaly); _context.SaveChanges();anomaly对象是请求中的对象。 -
对于
ChangeLog部分,我在this example 之后重写了SaveChanges()方法,并且旧/原始和新/当前值设置如下:auditEntry.OldValues[propertyName] = property.OriginalValue; auditEntry.NewValues[propertyName] = property.CurrentValue;基本上,这会遍历来自
ChangeTracker的所有条目,创建一个AuditEntry并在base.SaveChanges()之后返回并设置该 AuditEntry 的 EntityId,因为您在保存更改之前没有它(这是在如果您添加一个新实体,则保存更改后不会发生任何更新)。
Update() 方法正在工作,更改会反映在数据库中。但唯一的问题是ChangeLogs,来自ChangeTracker.Entries() 的条目不知道OldValues。
我承认我并不完全了解 EF 使用的跟踪系统,但我认为它应该可以帮助我更新实体而不是造成问题。因为我知道打电话给_context.DetachAllEntities();是不正确的。我尝试使用AsNoTracking() 并删除DetachAllEntities(),但结果似乎是一样的。我考虑过使用 dbEntity,将每个字段从请求实体复制到数据库实体,然后复制Update(dbEntity),但这似乎需要做很多工作,基本上是为了一点点好处。我的Anomaly 实体有很多导航属性,很难为其创建复制方法并进行维护。
DetachAllEntities() 是这样定义的:
public static void DetachAllEntities(this DbContext context)
{
var entries = context.ChangeTracker.Entries().ToList();
foreach (var entry in entries)
{
entry.State = EntityState.Detached;
}
}
DbContext 设置为 Scoped 生命周期,经理也是。
我也尝试使用this tutorial的审核方法,但结果是一样的。
我担心整个更新过程没有正确完成,因此会出现这个问题..
更新 我创建了一个示例项目来说明这个问题。 You can check the source code on bitbucket。自述文件有更多关于此的信息
我序列化了从上下文中检索到的对象。
欢迎任何建议、意见、新想法、评论。谢谢!
【问题讨论】:
-
我认为“DetachEntities”是您问题的根源。分离将从更改跟踪中删除实体,因此原始值和更改值不会更改..
-
好的。但是我尝试不使用它,但在调用 Update() 时出现错误:“实体已被跟踪”。所以,没有它,我什至无法保存我的更改
-
值得看看这个库,看看它是如何完成的——或者甚至只是引入它的引用并直接使用它——它可能会让你头疼:github.com/Arch/AutoHistory -为了为您的特定问题提供更具体的答案 - 我们可能需要查看更多代码,在上下文中了解发生了什么
-
我会看看那个库。非常感谢!另外,我会尽量提供一个小项目,下班后重现问题
-
问题已更新为示例项目以说明问题
标签: c# entity-framework asp.net-core .net-core entity-framework-core