EF Core如何获取实体原始值 EF Core OriginalValues获取方法

来源:这里教程网 时间:2026-02-21 17:34:06 作者:

在 EF Core 中,获取实体的原始值(即从数据库加载时的初始值)主要通过

ChangeTracker
OriginalValues
属性实现。它适用于跟踪已修改但尚未保存的实体,常用于审计、并发控制或生成更新语句时对比变化。

通过 EntityEntry 获取 OriginalValues

当你有实体实例且它已被上下文跟踪时,先用

Entry()
获取其
EntityEntry
,再访问
OriginalValues

适用场景:实体已加载(如通过
Find()
或查询获得),且后续被修改过
示例代码
var post = context.Posts.Find(1);
post.Title = "新标题";
post.Content = "已更新内容";
var entry = context.Entry(post);
var originalTitle = entry.OriginalValues["Title"]; // 返回旧标题
var originalContent = entry.OriginalValues["Content"]; // 返回旧内容
注意:若实体是新建(
Added
状态),
OriginalValues
为空(所有字段为
null
或默认值),因为没有“原始数据库值”

OriginalValues 是只读快照,不可直接修改

OriginalValues
是一个只读的属性快照,反映实体被加载时数据库中的值。你不能通过它来“重置”原始值或影响跟踪行为:

调用
entry.OriginalValues["Title"] = "xxx"
不会改变原始值,也不会触发任何状态变更
如需手动恢复原始值,应赋值给实体属性本身:
post.Title = entry.OriginalValues["Title"].ToString();
若想强制刷新原始值(例如模拟“放弃修改”),需重新查询或调用
entry.Reload()
(会覆盖当前所有修改并重置
OriginalValues

批量获取所有原始值并转为字典

方便日志记录或对比分析时,可将

OriginalValues
转成键值对字典:

var originalDict = entry.OriginalValues.ToDictionary(kvp => kvp.Metadata.Name, kvp => kvp.Value);
配合
CurrentValues
可快速找出哪些字段被改过:
var modifiedProps = entry.Properties
    .Where(p => !object.Equals(p.OriginalValue, p.CurrentValue))
    .Select(p => p.Metadata.Name)
    .ToList(); // 如 ["Title", "UpdatedAt"]

OriginalValues 在并发冲突中的作用

当使用乐观并发控制(如带

[ConcurrencyCheck]
IsRowVersion()
的字段)时,EF Core 会在生成 UPDATE 语句时自动使用
OriginalValues
中的值做 WHERE 条件:

例如:UPDATE Posts SET Title=@p0 WHERE Id=@p1 AND Version=@p2(@p2 来自
OriginalValues["Version"]
若数据库中该行的
Version
已变,执行返回 0 行受影响,EF Core 抛出
DbUpdateConcurrencyException
此时可在异常处理中访问
exception.Entries[0].OriginalValues
databaseValues
做合并决策

基本上就这些。OriginalValues 不复杂但容易忽略——关键记住它只对

Modified
Unchanged
状态的已跟踪实体有效,且本质是只读快照。

相关推荐