.NET 8 ASP.NET Core应用添加MySQL健康检查时触发ArgumentNullException(连接字符串为空)
这个问题的核心是你配置加载顺序搞反了,而且在Azure App Configuration的配置还没加载完成时,就提前读取了连接字符串,导致传给MySQL健康检查的参数是空值,触发了ArgumentNullException。
问题出在哪?
看你的代码流程就能发现问题:
- 你先从本地配置里读取了
ConnectionStringsSettings并赋值给connectionStringsOptions - 之后才把Azure App Configuration添加到配置源中
- 最后用提前读取的空连接字符串调用
AddMySql
这时候connectionStringsOptions.MyConnectionString只有本地配置里的值(如果本地没有就是null)——因为Azure的配置是在你读取配置之后才添加的,根本没机会覆盖这个变量的值。后面的builder.Services.Configure<ConnectionStringsSettings>只是注册了配置绑定规则,但不会更新你已经拿到的connectionStringsOptions变量。
两种可行的解决方案
方案1:调整配置加载顺序(推荐)
先把Azure App Configuration添加到配置源,再读取连接字符串。这样读取配置的时候就已经包含了从Azure拉取的内容:
if (!builder.Environment.IsDevelopment()) { // 第一步:先把Azure App Configuration加入配置源 builder.Configuration.AddAzureAppConfiguration(options => { options.Connect(new Uri(azureAppConfigurationOptions.Uri), new DefaultAzureCredential(defaultAzureCredentialOptions)); options.ConfigureKeyVault(kv => { kv.SetCredential(new DefaultAzureCredential(defaultAzureCredentialOptions)); }); }); // 第二步:再从包含Azure配置的Configuration里读取连接字符串 builder.Services.AddAzureAppConfiguration(); IConfigurationSection configurationConnectionStringsSection = builder.Configuration.GetSection(ConnectionStringsSettings.Section); builder.Services.Configure<ConnectionStringsSettings>(configurationConnectionStringsSection); ConnectionStringsSettings? connectionStringsOptions = configurationConnectionStringsSection.Get<ConnectionStringsSettings>() ?? throw new InvalidOperationException($"Invalid settings for {nameof(ConnectionStringsSettings)}"); builder.Services .AddHealthChecks() .AddApplicationStatus("Self") .AddMySql(connectionStringsOptions.MyConnectionString); }
方案2:延迟加载连接字符串(适合无法调整顺序的场景)
使用AddMySql的重载方法,通过服务容器动态获取连接字符串——这样连接字符串会在健康检查执行时才去读取,而不是启动时:
builder.Services .AddHealthChecks() .AddApplicationStatus("Self") .AddMySql( // 从服务容器中获取已绑定的最新配置 sp => sp.GetRequiredService<IOptions<ConnectionStringsSettings>>().Value.MyConnectionString, // 可按需配置健康查询、超时等参数 healthQuery: "SELECT 1;", timeout: TimeSpan.FromSeconds(5) );
这种方式不需要提前读取connectionStringsOptions,而是在健康检查真正执行时才从IOptions<ConnectionStringsSettings>里拿值,这时候Azure的配置已经加载完成,绑定也完全生效了。
额外提醒
builder.Services.Configure<ConnectionStringsSettings>只是注册了配置的绑定规则,不会自动更新你已经提前读取到变量里的配置值。如果配置源(比如Azure App Configuration)是在读取变量之后添加的,变量里的值不会同步更新,这是很多人容易踩的小坑。
备注:内容来源于stack exchange,提问作者Terai

