.NET 8 Core Worker Service发布为Windows服务时连接字符串未初始化错误
.NET 8 Worker Service 作为Windows服务运行时数据库连接字符串未初始化问题
问题现象
开发的.NET 8 Core Worker Service在Visual Studio调试/Release模式下可正常读写数据库,但发布为Windows Server服务运行时,日志抛出System.InvalidOperationException: The ConnectionString property has not been initialized错误,触发点是首次调用LOGGING上下文查询服务最后运行时间的操作。已确认appsettings.json连接字符串格式正确,同时在Program.cs和DbContext类中配置了连接字符串,不清楚调试与服务运行的核心差异,请求排查指导。
相关代码片段
Program.cs
// Program.cs相关代码 Environment.SetEnvironmentVariable("APP_BASE_DIRECTORY", WindowsServiceHelpers.IsWindowsService() ? AppContext.BaseDirectory : Directory.GetCurrentDirectory()); var host = Host.CreateDefaultBuilder(args) .UseWindowsService() .UseSerilog((context, services, configuration) => configuration .ReadFrom.Configuration(context.Configuration) .ReadFrom.Services(services)) .ConfigureServices((hostContext,services) => { services.AddHostedService<Worker>(); services.AddDbContext<DRADPRES>(options => options.UseSqlServer(hostContext.Configuration.GetConnectionString("DRADPRESCON"))); services.AddDbContext<LOGGING>(options => options.UseSqlServer(hostContext.Configuration.GetConnectionString("DRADPRESCON"))); services.AddDbContext<PS360>(options => options.UseSqlServer(hostContext.Configuration.GetConnectionString("PS360CON"))); services.AddHttpClient(); services.AddTransient<IEmailSender, EmailSender>(); }) .Build(); await host.RunAsync();
appsettings.json
// appsettings.json相关配置 { "ConnectionStrings": { "DRADPRESCON":"Server=VSRADDLSQLRSHAO,57650;Database=DRADPRES;User=yRADPRES;Password=*******;TrustServerCertificate=True", "PS360CON":"Server=VSRADPPSSQLAO,50151;Database=Comm4;Trusted_Connection=True;TrustServerCertificate=True" } }
LOGGING.cs DbContext
// LOGGING.cs上下文相关代码 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder.UseSqlServer("Server=VSRADDLSQLRSHAO,57650;Database=DRADPRES;User=yRADPRES;Password=******;TrustServerCertificate=True");
排查与解决方案
核心问题分析
- DbContext配置冲突:LOGGING DbContext中重写的
OnConfiguring方法硬编码了连接字符串,同时Program.cs又通过依赖注入配置了连接字符串。服务运行时可能出现配置加载优先级问题,若硬编码的连接字符串存在占位符(比如密码是******),就会导致初始化失败。 - 配置文件路径问题:Windows服务默认工作目录是
C:\Windows\System32,而非程序发布目录。即使设置了APP_BASE_DIRECTORY,默认配置加载逻辑可能仍从当前工作目录读取文件,导致服务找不到正确的appsettings.json,进而无法读取连接字符串,只能使用硬编码的无效值。
具体修复步骤
- 移除DbContext中的硬编码配置:删除LOGGING.cs中的
OnConfiguring重写方法,完全依赖依赖注入的配置,避免冲突:public class LOGGING : DbContext { public LOGGING(DbContextOptions<LOGGING> options) : base(options) { } // 你的DbSet定义等其他代码 } - 确保配置文件随发布复制:在Visual Studio中右键appsettings.json,设置复制到输出目录为始终复制,保证发布时配置文件和程序一起部署。
- 显式指定配置文件路径(可选):若服务仍无法加载配置,可在
Host.CreateDefaultBuilder中基于APP_BASE_DIRECTORY显式指定路径:var baseDir = Environment.GetEnvironmentVariable("APP_BASE_DIRECTORY"); var host = Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((context, config) => { config.SetBasePath(baseDir) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json", optional: true) .AddEnvironmentVariables(); }) .UseWindowsService() // 其他原有配置... - 指定服务工作目录:安装服务时,通过命令行指定服务工作目录为程序发布目录,避免默认使用System32:
sc config YourServiceName WorkingDirectory= "C:\Path\To\Your\Service\Publish\"
调试与服务运行的核心差异
- 工作目录不同:调试时工作目录是项目目录,服务默认是
C:\Windows\System32,影响相对路径文件的读取。 - 权限不同:服务默认使用LocalService等系统账户,调试时用当前登录用户账户,可能存在资源访问权限差异(但本次错误核心是连接字符串初始化问题)。
- 配置加载逻辑:服务运行时环境变量、配置文件的加载优先级与调试模式略有差异,多配置源共存时易出现冲突。
内容的提问来源于stack exchange,提问作者Ishhh
相关产品推荐
相关产品推荐

