c# 连接sql server数据库

连接字符串错误是引发SqlException或超时的主因,需区分Windows与SQL Server身份验证格式;Open()才建立物理连接,须用try/catch捕获特定错误号;using确保自动释放连接,连接池默认启用。

连接字符串写错会导致 SqlException 或超时

最常见的失败不是代码逻辑问题,而是 connectionString 格式或参数不匹配。SQL Server 支持 Windows 身份验证和 SQL Server 身份验证两种方式,二者连接字符串结构差异明显:

  • Windows 身份验证(推荐开发环境):"Server=localhost\\SQLEXPRESS;Database=MyDB;Trusted_Connection=True;"
  • SQL Server 身份验证(常见于生产或远程实例):"Server=192.168.1.100,1433;Database=MyDB;User Id=myuser;Password=mypass;"

注意:localhost\\SQLEXPRESS 中的双反斜杠是 C# 字符串转义要求;若用逐字字符串(@""),应写作 @"localhost\SQLEXPRESS"。端口未显式指定时默认为 1433,但命名实例(如 SQLEXPRESS)必须启用 SQL Server Browser 服务,否则可能连不上。

SqlConnection 必须显式调用 Open() 才建立物理连接

new SqlConnection(connectionString) 只创建对象,不触发网络连接。真正握手发生在调用 Open() 时——这也是异常最常抛出的位置。务必用 try/catch 包裹,并检查 SqlException.Number 做针对性处理:

try
{
    using (var conn = new SqlConnection(connStr))
    {
        conn.Open(); // ← 真正连接在此发生
        // 后续操作
    }
}
catch (SqlException ex)
{
    switch (ex.Number)
    {
        case 2: Console.WriteLine("服务器不可达,请检查网络或实例名");
        case 18456: Console.WriteLine("登录失败,用户名或密码错误");
        case 4060: Console.WriteLine("数据库名不存在或无法访问");
        default: throw;
    }
}

使用 using 语句确保连接及时释放

SQL Server 连接数有限(尤其 Express 版默认最大 10000),不释放会快速耗尽资源,后续请求直接卡在 Open() 等待。C# 的 using 不仅自动调用 Dispose(),还会隐式调用 Close() —— 即使发生异常也能保证清理:

  • ❌ 错误写法:var conn = new SqlConnection(...); conn.Open(); /* 忘记 close/dispose */
  • ✅ 正确写法:using (var conn = new SqlConnection(...)) { conn.Open(); /* 自动关闭 */ }

注意:SqlConnection 实现了连接池,默认开启。调用 Close() 并非断开 TCP,而是将连接归还池中复用。因此频繁 new + Close() 是安全且高效的,不必手动缓存 SqlConnection 对象。

查询执行前确认数据库状态和权限

连接成功不等于能执行命令。常见静默失败场景包括:

  • 数据库处于 RESTORINGOFFLINE 状态 → 查看 sys.databasesstate_desc
  • 登录用户无 CONNECT 权限 → 在 SSMS 中右键登录名 → “属性” → “用户映射” → 勾选对应数据库并赋予 db_datareader 等角色
  • 防火墙阻止 1433 端口(Windows Server 默认关闭入站规则)→ 检查 Windows Defender 防火墙 → 高级设置 → 入站规则

一个容易被忽略的点:如果应用部署在容器或不同主机,localhost 指向的是容器/本机回环,而非宿主 SQL Server。此时必须用宿主机 IP 或配置 Docker 网络别名。