SqlConnection连接失败主因是连接字符串格式或参数错误,如本地Express实例应写“.\SQLEXPRESS”,Windows认证推荐“Server=.;Database=testdb;Integrated Security=true”,SQL认证需启用混合模式并赋权;执行命令须用using管理资源、参数化防注入;按需选用ExecuteScalar(单值)、ExecuteNonQuery(增删改返回行数)、ExecuteReader(多行结果);异步方法需连接字符串含“Asynchronous Processing=true”且正确await。

SqlConnection 连接字符串写不对,连不上就是它的问题
SQL Server 连接失败,八成出在 connectionString。不是密码错,也不是服务没开,而是格式或参数填错了。本地 SQL Server Express 默认实例名是 .\SQLEXPRESS,不是 localhost 或 127.0.0.1;如果用的是命名实例,得写成 .\实例名。
常见错误现象:SqlException: A network-related or instance-specific error occurred...
使用场景:开发机直连、Docker 容器内连接、局域网服务器连接,参数差异很大
建议这样写(以本地 Express 实例 + Windows 认证为例):"Server=.;Database=testdb;Trusted_Connection=true;"
若用 SQL 账号密码,必须显式启用混合认证,并确保账号有登录权限:"Server=.;Database=testdb;User Id=sa;Password=yourpass;"
注意:Trusted_Connection=true 和 Integrated Security=true 等价,但后者在 .NET Core/.NET 5+ 中更推荐;Server=. 表示本地默认实例,Server=(local) 也行,但不推荐用 localhost(可能走 TCP 而非命名管道,触发额外防火墙规则)
用 SqlCommand 执行增删改查,别忘了 using 和参数化
SqlCommand 本身不维护连接状态,必须自己管好打开/关闭,否则连接池耗尽、超时、资源泄漏全来了。最稳妥的方式是把 SqlConnection 和 SqlCommand 都包进 using 块。
容易踩的坑:
- 直接拼接字符串执行
INSERT INTO users VALUES ('" + name + "')→ SQL 注入高危 - 忘记调用
cmd.ExecuteNonQuery()(增删改)或cmd.ExecuteReader()(查),结果语句根本没发出去 - 查询后没读完
SqlDataReader就丢弃,连接不会自动释放
正确做法(以插入为例):
using (var conn = new SqlConnection(connStr))
{
conn.Open();
using (var cmd = new SqlCommand("INSERT INTO users (name, age) VALUES (@name, @age)", conn))
{
cmd.Parameters.AddWithValue("@name", "张三");
cmd.Parameters.AddWithValue("@age", 25);
cmd.ExecuteNonQuery(); // 注意:这里必须调
}
}查询用 ExecuteReader,记得用 while (reader.Read()) 逐行取值,字段用 reader["name"] 或 reader.GetString(0) 获取。
ExecuteScalar、ExecuteNonQuery、ExecuteReader 三个方法怎么选
这三个方法返回值和用途完全不同,混用会导致逻辑错误或异常:
-
ExecuteScalar():只取结果集第一行第一列,适合SELECT COUNT(*)、SELECT MAX(id)这类聚合或单值查询。返回object,常要手动转类型,比如(int)cmd.ExecuteScalar() -
ExecuteNonQuery():用于INSERT/UPDATE/DELETE,返回受影响行数(int)。如果返回 -1,说明语句是CREATE、ALTER等 DDL,不是 DML -
ExecuteReader():返回SqlDataReader,适合多行多列结果。必须配合while (r.Read())使用,且不能在 reader 关闭前再次执行命令(同一连接上)
性能影响:
-
ExecuteScalar比ExecuteReader轻量,但别为了省一行代码在该用 reader 的地方硬套 scalar -
ExecuteNonQuery不加载结果集,比 reader 快,但别指望它返回自增 ID —— 得加SELECT SCOPE_IDENTITY()或用OUTPUT INSERTED.id
异步方法(ExecuteNonQueryAsync 等)不是“加上 Async 就变快”
ExecuteNonQueryAsync、ExecuteReaderAsync 这些方法底层依赖 SQL Server 的异步网络 I/O(需开启 Asynchronous Processing=true 在连接字符串里),不是简单把同步方法包一层线程。
常见误区:
- 在 WinForms/WPF 同步上下文里直接 await 异步方法,可能死锁(尤其没配
ConfigureAwait(false)) - ASP.NET Core 中不 await,导致连接提前释放、查询中断
- 连接字符串漏了
Asynchronous Processing=true,异步方法会退化成同步执行(.NET Framework 下较明显,.NET Core+ 默认支持更好,但仍建议显式开启)
正确姿势(ASP.NET Core Controller 示例):
public async Task<IActionResult> AddUser()
{
using var conn = new SqlConnection(connStr);
await conn.OpenAsync(); // 注意这里是 OpenAsync
using var cmd = new SqlCommand("INSERT ...", conn);
cmd.Parameters.AddWithValue("@name", "李四");
await cmd.ExecuteNonQueryAsync(); // 必须 await
return Ok();
}真正容易被忽略的是:连接字符串里的 Asynchronous Processing=true 在旧项目迁移时经常被遗漏,结果测不出异步效果,还误以为框架有问题。


















