如何配置audit.net(EF扩展)实现单对象审计并处理主键查询?
1. 为每个变更对象生成单独审计记录
可以通过Audit.NET Entity Framework扩展的配置实现将事务中的每个实体变更拆分为独立审计记录,无需自定义数据提供程序。核心是使用SplitAuditEntries方法,它会将原事务级的审计条目拆分为每个实体变更对应一条记录。
示例配置(可放在DbContext的OnConfiguring方法或全局初始化代码中):
Audit.EntityFramework.Configuration.Setup() .ForContext<YourAuditDbContext>(config => config // 自定义审计事件类型,便于区分不同实体的操作 .AuditEventType("{context}:{entity}:{action}") // 拆分每个实体变更为单独审计条目 .SplitAuditEntries(entry => entry.Entries));
配置后,每次SaveChanges/SaveChangesAsync执行时,每个被修改的实体(新增、更新、删除)都会生成一条独立的审计记录,而非整个事务对应一条。
2. 处理不同主键命名的暴露方案
针对不同表主键命名差异,最优方式是利用Audit.NET内置的主键识别能力,将主键值统一提取为标准化字段,避免依赖具体列名:
方案一:提取主键到审计记录的自定义字段
通过AuditEntityAction钩子,自动识别实体主键并将其存入审计记录的自定义字段,同时记录实体类型,方便后续按主键+实体类型查询:
Audit.EntityFramework.Configuration.Setup() .ForContext<YourAuditDbContext>(config => config .SplitAuditEntries(entry => entry.Entries) .AuditEntityAction((auditEvent, entry, entity) => { // 自动获取实体主键值(Audit.NET会识别EF实体的主键定义) var primaryKeyValue = entry.PrimaryKey.FirstOrDefault()?.Value; // 添加标准化字段到审计记录 auditEvent.CustomFields["EntityPrimaryKey"] = primaryKeyValue?.ToString(); auditEvent.CustomFields["EntityTypeName"] = entry.EntityType.Name; }));
如果使用SQL存储审计数据,可以在你的审计日志表(如AuditLogs)中新增EntityPrimaryKey和EntityTypeName列,配置Audit.NET将这些自定义字段映射到数据库列,这样查询时直接通过这两列过滤,无需解析JSON。
方案二:解析JSON中的主键
如果保留原JSON存储结构,查询逻辑可以根据实体类型,从JSON的PrimaryKey节点中提取对应值。审计记录的JSON会包含PrimaryKey数组,其中每个元素包含ColumnName和Value,可根据实体类型匹配对应的列名获取值。但这种方式查询效率低于方案一,适合无需频繁按主键查询的场景。
内容的提问来源于stack exchange,提问作者Thomas Renger

