VB.NET中SqlDataReader的HasRows为true却报无数据读取错误
问题原因分析
1. 代码存在变量拼写错误,对象引用混乱
你声明的本地命令对象名为myxDBcmd,但执行ExecuteReader时用的是无x前缀的myDBCmd(大概率是全局的旧命令对象),你给本地myxDBcmd添加的@branch参数根本没有生效,实际执行的是全局对象残留的其他查询逻辑,这是最核心的代码错误。
2. 调试器操作消耗了DataReader流
SqlDataReader是只进、只读的流式读取对象,你在断点处用鼠标悬浮查看reader的行列表、或在立即窗口枚举reader内容时,调试器会自动遍历所有行把流读完,游标直接移动到末尾,此时你再尝试读取字段自然会报“无数据”的错误。
3. 全局单例连接的潜在风险
全局复用数据库连接很容易出现资源占用、上下文冲突问题,你提到只有菜单触发的代码有问题,大概率是菜单事件的执行上下文和按钮事件不一致,跨线程访问共享连接对象导致DataReader状态异常。
修复方案
- 先修复代码的变量拼写问题,开启
Option Explicit和Option Strict避免后续出现同类隐式声明错误,同时用完DataReader后主动释放资源:
Private Sub RecoverUnsentOrderToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles RecoverUnsentOrderToolStripMenuItem.Click ' 查找当前网点状态为“1”的订单:已创建但未收到服务器回执 Dim myxDBReader As SqlDataReader Dim myxDBcmd As SqlCommand Dim query As String query = "select * from orders where branch = @branch and status = 1;" ' 统一使用本地声明的命令对象,不要混用全局对象 myxDBcmd = New SqlCommand(query, myDBCnn) myxDBcmd.Parameters.Add("@branch", SqlDbType.VarChar).Value = BranchCode myxDBReader = myxDBcmd.ExecuteReader If myxDBReader.HasRows Then Do While myxDBReader.Read ' 先把字段值赋值给本地变量,直接查看变量即可避开调试器消耗流的问题 Dim firstColVal As String = myxDBReader(0).ToString() Stop Loop End If ' 主动释放资源,避免占用连接 myxDBReader.Close() myxDBcmd.Dispose() End Sub
- 后续建议废弃全局单例连接的设计,ADO.NET自带连接池机制,每次操作数据库时新开连接、用完立即关闭即可,连接池会自动处理连接复用逻辑,比手动维护全局连接稳定很多。
- 检查菜单事件的执行线程,确认没有跨线程访问数据库连接的情况。
内容的提问来源于stack exchange,提问作者droopsnoot
相关产品推荐
相关产品推荐

