MNi*_*Nie 5 c# entity-framework-core .net-core asp.net-core ef-core-3.1
将 EF Core 3.1.5(从 2.2 迁移后)与 Autofac 5.2.0 一起使用时,我遇到了内存泄漏。我的情况是,在主页上我加载了一些产品列表,每次重新加载页面都会增加 5-10mb 的内存使用量,内存无休止地增加。它永远不会下降。我怀疑我的注册错误(?)或者这是因为 EF Core 中的跟踪行为(?)。我尝试注册我的MyDbContext的如下:
public class DbContextModule<TContext> : Module
where TContext : DbContext
{
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
builder
.RegisterType<TContext>()
.WithParameter("options", DbContextOptionsFactory.Get<TContext>())
.InstancePerLifetimeScope();
}
}
public class DbContextOptionsFactory
{
public static DbContextOptions<TContext> Get<TContext>() where TContext : DbContext
{
var confSql = "fake";
var builder = new DbContextOptionsBuilder<TContext>();
DbContextConfigurer.Configure<TContext>(builder, confSql);
return builder.Options;
}
}
public class DbContextConfigurer
{
public static void Configure<TContext>(DbContextOptionsBuilder<TContext> builder, string connectionString) where TContext : DbContext
{
builder.UseSqlServer(connectionString, sqlServerOptionsAction: sqlOptions =>
{
sqlOptions.EnableRetryOnFailure(
maxRetryCount: 3,
maxRetryDelay: TimeSpan.FromSeconds(3),
errorNumbersToAdd: null);
});
}
}
Run Code Online (Sandbox Code Playgroud)
并在启动文件中:
public void ConfigureContainer(ContainerBuilder builder)
{
...
builder.RegisterModule<DbContextModule<MyDbContext>>();
...
}
Run Code Online (Sandbox Code Playgroud)
我尝试添加AsSelf或ExternallyOwned但没有任何改变。我也尝试通过 Microsoft DI 注册 DbContext,但没有任何改变。尝试使用AddDbContextPoolonServiceCollection但仍然没有成功。
使用 EF Core 2.2 时不会出现上述问题。
在通过 DotMemory 进行一些调查后,我发现通过 ServiceProviderCache 出现了一些内存使用高峰。当我尝试使用谷歌搜索时,ServiceProviderCache EF Core我发现了以下链接。
在我的情况下,问题是我在本地启用控制台日志记录,以便在迁移后更容易地发现 ef core 的问题。DbContext 看起来像这样:
private readonly ILoggerFactory _loggerFactory;
public MyContext(DbContextOptions<MyContext> options)
: base(options)
{
_loggerFactory = LoggerFactory.Create(b => b.AddConsole());
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
if (``it is a local run``)
{
optionsBuilder
.UseLoggerFactory(_loggerFactory)
.EnableSensitiveDataLogging();
}
}
Run Code Online (Sandbox Code Playgroud)
有问题的线路是:
public MyContext(DbContextOptions<MyContext> options)
: base(options)
{
_loggerFactory = LoggerFactory.Create(b => b.AddConsole());
}
Run Code Online (Sandbox Code Playgroud)
根据 GitHub 上的答案,每次创建 DbContext 时都会创建记录器,此后不会销毁它。解决方案是使用静态记录器。所以我重构如下:
创建控制台记录器:
public class ConsoleLogger
{
public readonly ILoggerFactory Instance;
public ConsoleLogger()
{
Instance = Microsoft.Extensions.Logging.LoggerFactory.Create(x => x.AddConsole());
}
}
Run Code Online (Sandbox Code Playgroud)
将其注册为单例:
...
builder.RegisterType<ConsoleLogger>().AsSelf().SingleInstance();
...
Run Code Online (Sandbox Code Playgroud)
并在 DbContext 中像这样使用它:
public MyContext(DbContextOptions<MyContext> options, ConsoleLogger consoleLogger)
: base(options) =>
_consoleLogger = consoleLogger;
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
if (``it is a local run``)
{
optionsBuilder
.UseLoggerFactory(_consoleLogger.Instance)
.EnableSensitiveDataLogging();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
505 次 |
| 最近记录: |