SqlConnection+SqlCommand+SqlDataReader/SqlDataAdapter是最可控、最贴近SQL本质的原生方式,适合调试、学习及高性能/事务场景,但需手动管理连接、参数化查询、资源释放与超时设置。
直接说结论:用++或是最可控、最贴近 SQL 本质的原生方式,适合调试、学习和对性能/事务有明确要求的场景;但必须手动管理连接生命周期、参数防注入、资源释放,漏掉任何一环就容易出错。
SqlConnection 连接字符串写错或没开权限,连不上怎么办
常见错误现象是抛出
,消息里带 “A network-related or instance-specific error…” 或 “Login failed for user…”。
检查连接字符串中
(实例名)是否正确,本地默认实例可写
或
,命名实例要带
,比如
(数据库名)必须已存在,不能是空库名或拼错;SQL Server Express 默认不启用 TCP/IP,需在 SQL Server 配置管理器中打开
Windows 身份验证用
;SQL 账户登录必须确保
或指定用户已启用且密码正确,且服务器身份验证模式设为“SQL Server 和 Windows 身份验证模式”
连接字符串不要硬编码在代码里,优先从
(.NET Core/5+)或
读取,避免提交敏感信息
执行 INSERT/UPDATE/DELETE 时返回值总是 0
这通常不是 SQL 写错了,而是
返回的是“受影响行数”,不是“成功与否”的布尔值。如果 SQL 语法合法但没匹配到数据(比如 WHERE 条件不成立),它就真返回 0。
确认 SQL 语句本身能独立在 SSMS 中跑通,尤其是 WHERE 子句是否真能命中记录
务必使用参数化查询,别拼字符串——
是严重漏洞,也容易因单引号导致语法错误
正确写法是:
,然后 SQL 字符串里写
如果需要获取刚插入的自增 ID,别用
,改用
并配合
SqlDataReader 读完不 Close,程序卡死或内存暴涨
是连接态、只进、只读游标,它会一直占用底层连接,直到显式关闭或被 dispose。忘记关,后续操作就会阻塞在
上,或者引发“超时”“连接池已满”等错误。
C知道
CSDN推出的一款AI技术问答工具
下载
永远用
包裹:
—— 这能保证即使异常也会释放资源
不要在
循环里调
,也不要在循环外手动
,
已涵盖
如果只是查单行,用
更轻量;如果要加载整张表到内存做筛选/绑定,用
更合适
注意:DataReader 不支持多次遍历,读完就没了;想重复用,得重新执行命令或换用 DataTable
事务里多个 SqlCommand 共享同一个 SqlConnection 却报错
典型错误是
或 “There is already an open DataReader associated with this Connection”。根本原因是:一个
同一时刻只能有一个活跃的命令(包括 Reader、ExecuteNonQuery 等)。
事务内所有命令必须复用同一个
实例,并显式传入
对象给每个
的
属性
不能在一个连接上一边
,一边又
—— 必须等 Reader 关闭后才能执行下一个命令
如果事务跨多个方法,把
和
当作参数传进去,而不是在每个方法里 new 新连接
别依赖连接池自动回收:事务未
或
就丢弃连接对象,连接池会把它标记为“不可重用”,造成连接泄漏
最常被忽略的一点:原生 ADO.NET 没有自动重试、没有连接健康检查、没有命令超时自动取消(除非显式设
)。一旦网络抖动或 SQL 长时间卡住,整个线程就挂在那里。生产环境务必设
和
,并考虑封装一层带重试逻辑的执行器。
SqlConnectionSqlCommandSqlDataReaderSqlDataAdapterSqlExceptionServer.(local)\实例名DESKTOP-R6BQK8P\SQLEXPRESSInitial CatalogIntegrated Security=truesaappsettings.jsonApp.configExecuteNonQuery()"UPDATE users SET name = '" + name + "' WHERE id = " + idcmd.Parameters.AddWithValue("@name", name); cmd.Parameters.AddWithValue("@id", id);UPDATE users SET name = @name WHERE id = @idSELECT @@IDENTITYSELECT SCOPE_IDENTITY()ExecuteScalar()SqlDataReaderOpen()usingusing (var reader = cmd.ExecuteReader()) { while (reader.Read()) { ... } }while (reader.Read())reader.Close()Dispose()usingExecuteScalar()SqlDataAdapter.Fill(DataTable)SqlConnection does not support parallel transactionsSqlConnectionSqlConnectionSqlTransactionSqlCommandTransactionExecuteReader()ExecuteNonQuery()SqlConnectionSqlTransactionCommit()Rollback()CommandTimeoutConnection Timeout=30Command Timeout=60