ServiceProvider依赖注入松耦合场景下SQL数据库连接异常如何解决
问题根因
该问题和ServiceProvider依赖注入实现无关,属于架构设计缺陷+单例对象使用不当共同导致,具体触发逻辑如下:
- 你在
CRUDManager的业务方法中用using语句包裹了databaseManager.GetConnection()返回的SqlConnection实例,using代码块执行结束后会自动调用Dispose方法释放连接资源。 - 你的
DatabaseManager中把SqlConnection声明为静态全局单例对象,一旦被释放,后续所有方法再获取该连接实例时,拿到的都是已经销毁的无效对象,自然会报连接字符串为空、连接无效的错误。 - 单元测试未触发问题是因为单测通常单个用例单独初始化
DatabaseManager实例、单次调用方法,不会跨多次调用复用同一个连接实例。
另外注意你提供的代码中存在类名拼写错误(DatabaseMananger/CRUDMananger多写了字母n),需要先修正避免DI注入时找不到对应实现。
优化方案
推荐优先使用方案1,符合ADO.NET最佳实践:
- 方案1:调整连接获取逻辑,依赖ADO.NET连接池管理连接
SqlConnection本身内置连接池机制,不需要手动维持单例连接,每次需要连接时新建实例即可,修改DatabaseManager代码:
public class DatabaseManager: IDatabaseManager { private string _connectionString; public void SetConnection(string connectionString) { _connectionString = connectionString; } public SqlConnection GetConnection() { // 每次返回新的连接实例,底层连接池会自动复用物理连接,无性能损耗 return new SqlConnection(_connectionString); } }
该方案下每次using释放的只是当前方法的托管连接实例,不会影响后续方法的调用。
- 方案2(不推荐):手动管理全局连接生命周期
如果确实需要复用全局连接,禁止在业务方法中用using释放全局连接,手动控制连接的打开、关闭:
// CRUDManager方法示例 public string Read() { var conn = databaseManager.GetConnection(); try { if(conn.State != ConnectionState.Open) conn.Open(); // 执行读表逻辑 } finally { // 仅关闭连接,不释放对象,后续可复用 conn.Close(); } }
- 补充优化:依赖注入阶段初始化连接配置
可以把连接字符串在服务注册阶段直接传入,避免后续手动调用SetConnection,降低使用风险:
// 调整ConfigureServices中的服务注册逻辑 services.AddSingleton<IDatabaseManager, DatabaseManager>(sp => new DatabaseManager(connectionString)); // DatabaseManager新增构造方法 public class DatabaseManager: IDatabaseManager { private readonly string _connectionString; public DatabaseManager(string connectionString) { _connectionString = connectionString; } // 其余逻辑不变 }
内容的提问来源于stack exchange,提问作者mDigitalFrog
相关产品推荐
相关产品推荐

