EF Core如何实现审计日志 EF Core自动记录操作日志方法

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

EF Core 本身不内置审计日志功能,但可以通过拦截 SaveChanges 过程,在数据写入数据库前自动捕获实体的变更状态,从而实现轻量、统一的审计日志记录。核心思路是:在

DbContext
中重写
SaveChanges
/
SaveChangesAsync
,遍历所有被跟踪的实体,提取新增、修改、删除操作及字段级变化,并写入自定义审计日志表。

1. 定义审计日志实体

先创建一个标准的日志实体,用于存储操作人、时间、实体类型、操作类型(Add/Update/Delete)、关键字段变更等信息:

AuditLogId:主键(Guid 或 long) UserId:当前操作用户 ID(需从上下文或 ClaimsPrincipal 获取) EntityType:被操作的实体类名(如 "Order") EntityId:被操作实体的主键值(支持 string/int/Guid) Action:操作类型("Created", "Updated", "Deleted") ChangedFields:JSON 字符串,记录字段名、旧值、新值(仅 Update 时有差异) Timestamp:UTC 时间戳

2. 在 DbContext 中注入审计逻辑

重写

SaveChanges
方法,利用 EF Core 的
ChangeTracker
获取变更状态:

调用
ChangeTracker.Entries()
遍历所有状态为
Added
Modified
Deleted
的实体
对每个条目,提取主键值(
entry.Metadata.FindPrimaryKey().Properties
)和变更详情
对于
Modified
条目,用
entry.OriginalValues
entry.CurrentValues
对比字段差异
构造
AuditLog
实体并添加到当前上下文(注意:避免递归触发审计)
建议将审计日志实体加入
DbContext
时使用
Entry(log).State = EntityState.Added
而非
Add()
,防止与主 SaveChanges 冲突

3. 处理用户上下文与线程安全

获取当前用户 ID 是常见难点,推荐以下方式:

通过构造函数注入
IHttpContextAccessor
(需在
Program.cs
注册),从中读取
User.Identity.Name
或自定义 Claim
若非 Web 环境(如后台服务),可依赖外部传入的
CurrentUserId
(例如通过作用域服务或显式参数)
避免在审计逻辑中直接 await 异步操作(如查用户信息),保持同步处理;如必须异步,请改用
SaveChangesAsync
并确保日志写入也异步完成

4. 可选增强:字段级过滤与忽略

不是所有字段都需要审计(如

UpdatedAt
RowVersion
)。可通过以下方式控制:

给实体属性加自定义特性(如
[AuditIgnore]
),在审计逻辑中跳过标记字段
约定忽略以
Is
Has
Last
开头的布尔/时间戳字段
为敏感字段(如密码)强制脱敏:写入日志前替换为
"[REDACTED]"

基本上就这些。不需要第三方库也能跑起来,关键是把变更提取逻辑写稳、字段对比做准、用户上下文拿得对。小项目够用,大系统可在此基础上接入消息队列或 Elasticsearch 做异步归档。

相关推荐