You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VB.NET获取表最后插入ID时提示行或列无可用数据错误

VB.NET获取数据表最后插入ID报错排查

错误根因

触发There is no data available for the row or column错误的直接原因及代码现存问题:

  • OleDbDataReader使用逻辑不符合规范:ExecuteReader()执行完成后,DataReader初始指针位置位于第一行结果之前,未调用Read()方法移动指针到有效数据行就直接读取列值,是本次报错的直接原因。该问题和SQL本身正确性无关:SSMS执行查询时会自动完成结果集遍历的底层逻辑,代码中需要显式调用读取方法才能访问数据。
  • 资源释放逻辑完全失效:原代码将CONECTOR.Close()放在Return x语句之后,函数执行到Return时会直接退出,连接永远不会被手动关闭,持续运行会耗尽连接池触发连接超时错误。
  • 边界场景无兼容逻辑:若ordenproduccion表无任何记录,MAX(idOrdenProd)聚合函数会返回DBNull,直接做类型转换会抛出异常,原代码未对该场景做兜底。
  • 业务逻辑存在并发风险:通过MAX(主键)获取最后插入ID的写法,在多用户并发插入场景下会取到其他用户提交的最新ID,后续关联插入会造成数据关联错误。

修复方案

修正后的ID查询函数

Public Function BuscarUltimoidOrdenProd() As Integer
    ' Using块自动释放连接、命令、读取器资源,异常场景也会自动关闭连接
    Using CONECTOR As New OleDbConnection("Data Source=DESKTOP-DNN8GME\SQLEXPRESS; Initial Catalog=DB_Calcita;Provider=SQLOLEDB;Integrated Security=SSPI;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False")
        CONECTOR.Open()
        Dim SQL As String = "SELECT MAX(idOrdenProd) as idOrdenProd FROM ordenproduccion"
        Using cmd As New OleDbCommand(SQL, CONECTOR)
            cmd.CommandType = CommandType.Text
            Using dr As OleDbDataReader = cmd.ExecuteReader()
                ' 移动指针到第一行,确认存在有效数据再读取
                If dr.Read() Then
                    ' 兼容空表返回DBNull的场景
                    If IsDBNull(dr("idOrdenProd")) Then
                        Return 0
                    End If
                    Return Convert.ToInt32(dr("idOrdenProd"))
                Else
                    ' 无查询结果时返回业务默认值0
                    Return 0
                End If
            End Using
        End Using
    End Using
End Function

并发场景优化建议

如果需要获取当前数据库会话刚插入的生产订单ID,不要使用MAX()查询,应该在执行插入语句时直接通过SCOPE_IDENTITY()返回值获取对应ID,从根源避免并发取错ID的问题,示例逻辑:

' 插入语句末尾拼接SELECT SCOPE_IDENTITY(),直接返回当前会话插入的自增ID
Dim insertSql As String = "INSERT INTO ordenproduccion(字段1,字段2) VALUES(@值1,@值2); SELECT SCOPE_IDENTITY();"
Using cmd As New OleDbCommand(insertSql, CONECTOR)
    ' 补充参数赋值逻辑
    CONECTOR.Open()
    ' 执行Scalar直接拿到刚插入的ID,不需要额外发起MAX查询
    Dim newInsertId As Integer = Convert.ToInt32(cmd.ExecuteScalar())
End Using

修复要点说明

  • 移除类级别共享的全局CONECTOR对象:数据库连接不要作为全局变量长期持有,每次执行查询时创建新连接,由ADO.NET连接池自动管理复用,是官方推荐的最佳实践,可彻底避免连接状态混乱、连接泄漏问题。
  • 所有实现IDisposable接口的数据库对象(连接、命令、DataReader)全部放入Using块包裹,不需要手动编写Close()或Dispose()逻辑,代码执行到Using块末尾时会自动释放资源。
  • 所有通过DataReader读取数据的场景,必须先调用Read()方法,判断返回值为True(代表指针指向有效数据行)后,才能读取对应列的值。
  • 增加IsDBNull判断逻辑,兼容空表、查询返回空值的边界场景。

内容的提问来源于stack exchange,提问作者Joaquín Gomez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 14:42:16