You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Audit.Net更新时插入空记录并触发递归内存溢出问题排查

问题原因与解决方案

从你的描述和代码来看,这个递归审计导致内存溢出的问题,核心原因是AuditLog实体本身被纳入了审计范围,触发了无限递归的审计循环,具体分析和解决方法如下:

1. 核心问题:AuditLog的递归审计

你使用的AuditDbContext会自动跟踪并审计所有DbSet中实体的变更。当你保存一条AuditLog记录时,DbContext会检测到这个新增/修改操作,再次触发Audit.Net的审计流程,生成新的AuditLog记录——这个过程会无限循环下去,每次生成的AuditData JSON会包含更多的嵌套审计信息,最终耗尽内存抛出OutOfMemoryException。

另外,你重写的Entry<T>方法也存在隐患:

public new DbEntityEntry<T> Entry<T>(T entity) where T : class 
{ 
    return (new PContext().Entry(entity) as DbEntityEntry<T>); 
}

每次调用Entry都新建一个PContext实例,会导致实体跟踪上下文不一致,不仅可能加剧递归问题,还会引发其他数据操作的异常。

2. 解决方案

方案一:排除AuditLog实体的审计

你需要明确告诉Audit.Net不要审计AuditLog实体的变更,有两种方式:

  • 方式1:使用特性标记
    在AuditLog类上添加[AuditIgnore]特性:
[AuditIgnore]
public class AuditLog
{
    // 你的实体属性
}
  • 方式2:在配置中忽略实体
    修改Startup中的Audit配置,添加IgnoreEntity<AuditLog>():
Audit.Core.Configuration.Setup()
    .UseEntityFramework(_ => _
        .AuditTypeMapper(t => typeof(AuditLog))
        .AuditEntityAction<AuditLog>((ev, entry, entity) => 
        { 
            entity.AuditData = entry.ToJson(); 
            entity.AuditDate = DateTime.Now; 
            entity.AuditUser = Environment.UserName; 
            entity.AuditUsername = HttpContext.Current.User.Identity.Name; 
        })
        .IgnoreMatchedProperties(true)
        .IgnoreEntity<AuditLog>()); // 添加这一行

方案二:修复重写的Entry方法

将Entry<T>方法改为使用基类的实现,避免新建上下文:

public new DbEntityEntry<T> Entry<T>(T entity) where T : class 
{ 
    return base.Entry(entity); 
}

如果不需要自定义Entry逻辑,甚至可以直接删除这个重写方法,使用AuditDbContext的默认实现即可。

3. 验证修复

完成上述修改后,更新实体时Audit.Net只会生成一条对应的AuditLog记录,不会再触发递归,内存溢出问题也会随之解决。

内容的提问来源于stack exchange,提问作者nightowl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:05:47