ASP.NET Core中ConnectionString未初始化错误排查求助
问题分析与解决方案
核心问题
你遇到的The ConnectionString property has not been initialized.错误根源在于:
DataAccess类的ExecuteDataTableAsync是静态方法,但连接字符串connectionstring是在实例构造函数中赋值的静态字段- 调用静态方法时,
DataAccess的实例从未被创建过,导致connectionstring始终为null,最终创建SqlConnection时触发错误 - 手动创建
ConfigurationBuilder属于冗余操作,ASP.NET Core默认已加载appsettings.json等配置文件
分步修复
1. 简化Program.cs配置
删除手动创建ConfigurationBuilder的代码,WebApplication.CreateBuilder默认已完成配置加载:
public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); builder.Services.AddRazorPages(); // 注册DataAccess到依赖注入容器,选择Scoped生命周期适配Web场景 builder.Services.AddScoped<DataAccess>(); var app = builder.Build(); if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); app.UseHsts(); } app.UseStaticFiles(); app.UseRouting(); app.MapRazorPages(); app.Run(); }
2. 重构DataAccess类
移除静态成员,改为实例类,通过构造函数注入IConfiguration获取连接字符串:
public class DataAccess { private readonly string _connectionString; public DataAccess(IConfiguration configuration) { // 增加空值校验,提前发现配置问题 _connectionString = configuration.GetConnectionString("P51InvConnection") ?? throw new InvalidOperationException("未找到连接字符串P51InvConnection"); } // 改为实例方法,移除static修饰符 public async Task<DataTable> ExecuteDataTableAsync(string storedProcedureName) { return await ExecuteDataTableAsync(storedProcedureName, null!); } public async Task<DataTable> ExecuteDataTableAsync(string storedProcedure, params SqlParameter[] parameters) { DataTable dt = new DataTable(); try { // 使用SqlClient原生异步方法,避免不必要的线程切换 using SqlConnection conn = new(_connectionString); await conn.OpenAsync(); using SqlCommand cmd = new(storedProcedure, conn); cmd.CommandTimeout = 3; cmd.CommandType = CommandType.StoredProcedure; if (parameters != null) { cmd.Parameters.AddRange(parameters); // 用AddRange替代循环添加,提升效率 } using SqlDataAdapter da = new(cmd); da.Fill(dt); } catch (Exception ex) { Console.WriteLine(ex.ToString()); throw; // 重新抛出异常,让上层代码处理错误,避免吞掉异常导致问题隐蔽 } return dt; } // 保留静态方法,因为创建参数是无状态操作 public static SqlParameter Parameter(string parameterName, object parameterValue) { return new SqlParameter { ParameterName = parameterName, Value = parameterValue ?? DBNull.Value // 处理null值,避免传入null引发SqlParameter错误 }; } }
3. 修改数据库调用逻辑
通过依赖注入获取DataAccess实例,替换静态方法调用:
// 示例:在Razor Page的PageModel中注入DataAccess public class EntryPageModel : PageModel { private readonly DataAccess _dataAccess; public EntryPageModel(DataAccess dataAccess) { _dataAccess = dataAccess; } public async Task<IActionResult> OnGetAsync() { var entries = await GetEntryList(); // 后续业务逻辑 return Page(); } private async Task<List<Entry>> GetEntryList() { List<Entry> entryList = new(); DataTable dt = await _dataAccess.ExecuteDataTableAsync("[dbo].[OpenTransfer_Select]"); foreach (DataRow row in dt.Rows) { Entry entry = new() { Id = Convert.IsDBNull(row["Id"]) ? 0 : Convert.ToInt32(row["Id"]), UserId = Convert.IsDBNull(row["UserId"]) ? string.Empty : Convert.ToString(row["UserId"]), ItemNumber = Convert.IsDBNull(row["ItemNumber"]) ? string.Empty : Convert.ToString(row["ItemNumber"]), EntryDate = Convert.IsDBNull(row["TransferDate"]) ? Convert.ToDateTime("1/1/1900") : Convert.ToDateTime(row["TransferDate"]) }; entryList.Add(entry); } return entryList; } }
额外优化建议
- 避免用
Task.Run包装同步代码,直接使用SqlClient提供的异步API(如OpenAsync) - 可以创建强类型配置类绑定连接字符串,替代直接使用
IConfiguration,提升类型安全性 - 不要吞掉异常,捕获后记录日志并重新抛出,便于排查问题
内容的提问来源于stack exchange,提问作者Buck Hicks
相关产品推荐
相关产品推荐

