如何通过WebApplication.CreateBuilder让DataAccess类获取连接字符串
解决方案
1. 改造DataAccess类,支持依赖注入
把静态类改为实例类,通过构造函数注入连接字符串,避免硬编码:
public class DataAccess { private readonly string _connectionString; // 构造函数注入连接字符串 public DataAccess(string connectionString) { _connectionString = connectionString ?? throw new ArgumentNullException(nameof(connectionString)); } public async Task<DataTable> ExecuteDataTableAsync(string storedProcedure, params SqlParameter[] parameters) { DataTable dt = new DataTable(); try { // 使用注入的连接字符串初始化数据库连接 using SqlConnection conn = new(_connectionString); await conn.OpenAsync(); // 改用异步版的Open方法 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) { LogError(ex); throw; // 重新抛出异常,避免吞掉错误信息 } if (dt.Rows.Count == 0) { throw new Exception("DataTable empty"); } return dt; } private void LogError(Exception ex) { // 保留你的日志实现逻辑 Console.WriteLine($"Error: {ex.Message}"); } }
说明:
- 移除
static修饰符,改为实例类,才能通过依赖注入获取连接字符串 - 删掉不必要的
Task.Run,OpenAsync本身已是异步操作,无需额外线程包装 - 优化参数添加逻辑,用
AddRange替代循环 - 调整空DataTable的判断逻辑,避免冗余的空引用检查
2. 在Program.cs中注册服务并注入连接字符串
在WebApplication构建前,将DataAccess注册到服务容器,同时传入读取到的连接字符串:
var builder = WebApplication.CreateBuilder(args); // 读取并验证连接字符串 string? connectionString = builder.Configuration.GetConnectionString("P51InvConnection"); if (string.IsNullOrEmpty(connectionString)) { throw new InvalidOperationException("Connection string 'P51InvConnection' not found in configuration."); } // 注册DataAccess服务,可根据业务需求选择Scoped/Transient/Singleton builder.Services.AddScoped<DataAccess>(sp => new DataAccess(connectionString)); // 其他服务注册逻辑... var app = builder.Build(); // 中间件配置... app.Run();
说明:
- 先验证连接字符串是否存在,避免后续注入空值引发错误
AddScoped表示每个请求实例化一次DataAccess,可根据需求替换为AddTransient(每次获取都实例化)或AddSingleton(全局单例)
3. 在业务代码中注入DataAccess实例
比如在API控制器中使用:
[ApiController] [Route("[controller]")] public class InventoryController : ControllerBase { private readonly DataAccess _dataAccess; // 构造函数注入DataAccess实例 public InventoryController(DataAccess dataAccess) { _dataAccess = dataAccess; } [HttpGet] public async Task<IActionResult> GetInventory() { var parameters = new SqlParameter[] { new SqlParameter("@Status", "Active") }; var dataTable = await _dataAccess.ExecuteDataTableAsync("GetInventory", parameters); return Ok(dataTable); } }
替代方案:直接注入IConfiguration
如果不想单独传递连接字符串,也可以让DataAccess直接读取配置:
public class DataAccess { private readonly string _connectionString; public DataAccess(IConfiguration configuration) { _connectionString = configuration.GetConnectionString("P51InvConnection") ?? throw new InvalidOperationException("Connection string not found."); } // 后续方法逻辑同上... }
此时Program.cs的服务注册更简洁:
builder.Services.AddScoped<DataAccess>();
这种方式无需手动传递连接字符串,但DataAccess会和配置强耦合,灵活性不如直接注入字符串。
内容的提问来源于stack exchange,提问作者Buck Hicks
相关产品推荐
相关产品推荐

