sqlconnection必须用using包裹,否则连接池必然耗尽;不写using导致close()漏调、异常分支资源未释放,连接长期占用池槽位,最终引发timeout expired异常且需重启恢复。

SqlConnection 必须用 using 包裹,否则连接池很快耗尽,不是“可能出问题”,是“一定会在压测或上线后暴雷”。
SqlConnection 不写 using 会怎样
不加 using 意味着你手动管理 Open() 和 Close(),但现实里几乎没人能 100% 保证每条路径都调用 Close()——尤其是异常分支、return 提前退出、或者嵌套 try/catch 时漏掉。
后果很直接:
-
SqlConnection对象不会被及时释放,底层 socket 和网络句柄持续占用 - 连接池中的空闲连接数迅速归零,后续请求卡在
Waiting for connection pool - 错误日志里反复出现
Timeout expired. The timeout period elapsed prior to obtaining a connection... - 重启应用才能恢复,但下次照样崩
该用 Microsoft.Data.SqlClient 还是 System.Data.SqlClient
看 .NET 版本:
- .NET Core 3.1 及以后、.NET 5+(含 .NET 6/7/8/9)→ 必须用
Microsoft.Data.SqlClient(NuGet 包名同名),它是官方维护的跨平台继任者 - .NET Framework 4.6.1–4.8 → 可用
System.Data.SqlClient(已内置),但Microsoft.Data.SqlClient同样支持且更新更勤,推荐统一迁入 - 混用会导致编译失败或运行时
TypeLoadException:两个包定义了完全相同的类名和命名空间,但类型不兼容
安装命令只用一条:dotnet add package Microsoft.Data.SqlClient,别再搜“sqlclient nuget 哪个版本”。
连接字符串里 Trusted_Connection=true 和 Integrated Security=true 能互换吗
能,完全等价,都是启用 Windows 身份验证。但要注意:
- 仅在本地开发或域环境可靠;部署到 Linux 容器或 Azure App Service 时,
Integrated Security会直接失败(无 Kerberos 支持) - SQL Server 账户模式(
User Id/Password)才是生产首选,便于权限隔离和审计 - 若硬编码密码,请确认配置文件(如
appsettings.json)没被提交到 Git——检查.gitignore是否包含appsettings.*.json
一个安全的最小连接字符串示例:Server=myserver;Database=MyDB;User Id=appuser;Password=xxx;Connect Timeout=15;,其中 Connect Timeout 显式设为 15 秒,避免无限等待。
为什么连一次数据库要 new 两次对象:SqlConnection + SqlCommand
这不是冗余,是职责分离:
-
SqlConnection只管“通路”:建立 TCP 连接、维持会话、参与连接池复用 -
SqlCommand只管“指令”:SQL 文本、参数绑定、执行方式(ExecuteReader/ExecuteScalar/ExecuteNonQuery) - 同一个
SqlConnection实例可复用多个SqlCommand(比如查用户后再查订单),但每个SqlCommand必须显式关联Connection属性 - 漏设
cmd.Connection = conn会导致InvalidOperationException: Execute requires the command to have a connection
所以标准写法永远是:using (var cmd = new SqlCommand(sql, conn)) { ... },第二个参数不能省。
最常被忽略的点:连接字符串里的 Pooling=true(默认开启)意味着 Close() 并不真正断开网络,只是归还给池——所以你看到 conn.State == ConnectionState.Closed,不代表 socket 已关。这也正是为什么不用 using 就等于悄悄吃光池子。











