在DbContext中添加拦截器引发ManyServiceProvidersCreatedWarning异常
问题原因与解决方案
你遇到的ManyServiceProvidersCreatedWarning警告,核心原因是每次创建DbContext实例时,都在OnConfiguring方法里新建了一个IgnoreTrackingInterceptor实例。
EF Core会将DbContext的配置选项(包括添加的拦截器实例)作为判断配置唯一性的依据。如果每次配置都传入不同的拦截器实例引用,EF会判定这是全新的配置,进而为其创建新的IServiceProvider。当这类ServiceProvider的创建数量超过20时,就会触发该警告,长期运行还可能引发内存占用过高的问题。
解决方案
方案一:依赖注入注册单例拦截器(推荐,适用于ASP.NET Core等DI场景)
将拦截器注册为单例服务,确保所有DbContext实例共用同一个拦截器:
- 在DI容器中注册拦截器和DbContext:
// Program.cs 或 Startup.cs builder.Services.AddSingleton<IgnoreTrackingInterceptor>(); builder.Services.AddDbContext<YourDbContext>((serviceProvider, options) => { // 从DI容器获取单例拦截器实例 var interceptor = serviceProvider.GetRequiredService<IgnoreTrackingInterceptor>(); options.AddInterceptors(interceptor); // 其他数据库配置,例如SQL Server连接 options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")); });
- 移除DbContext中
OnConfiguring方法里手动添加拦截器的代码,避免重复配置。
方案二:使用静态单例拦截器(适用于无DI的场景)
把拦截器做成静态单例,确保每次添加的是同一个实例:
public class YourDbContext : DbContext { // 静态单例拦截器,全局唯一 private static readonly IgnoreTrackingInterceptor _singletonInterceptor = new IgnoreTrackingInterceptor(); protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { base.OnConfiguring(optionsBuilder); // 添加静态单例实例,而非每次新建 optionsBuilder.AddInterceptors(_singletonInterceptor); // 其他数据库配置 optionsBuilder.UseSqlServer("YourConnectionString"); } } public class IgnoreTrackingInterceptor : IMaterializationInterceptor { public object InitializedInstance(MaterializationInterceptionData materializationData, object instance) { if (instance is ISomeEntity someEntity) materializationData.Context.Entry(someEntity).State = EntityState.Detached; return instance; } }
修改后,所有DbContext实例都会共用同一个拦截器实例,EF Core不会再重复创建ServiceProvider,警告即可消除。你的拦截器业务逻辑本身没有问题,仅需调整实例化方式即可。
内容的提问来源于stack exchange,提问作者pantonis
相关产品推荐
相关产品推荐

