VB.NET连接Oracle 11g突发对象状态无效错误求助
问题:夜间批处理任务突然抛出"Operation is not valid due to the current state of the object"异常
我有一个每日夜间运行的批处理任务,此前一直执行成功,但今日突然抛出异常:Operation is not valid due to the current state of the object。未修改任何代码(该代码由他人编写),无法确定异常源于环境、代码还是数据。
经定位,异常发生在代码行:Dim rotate As Short = DirectCast(dr("ROTATE"), Short)
异常堆栈跟踪
Oracle.DataAccess.Client.OracleDataReader.GetOrdinal(String name)
Oracle.DataAccess.Client.OracleDataReader.get_Item(String columnName)
MyProject.Package.Filing.Core.Yakan.LinkDataCreate.ImageCreateWorker.Execute(Object obj)
相关代码
Public Sub Execute(ByVal obj As Object) Dim errorCount As Integer = 0 ' 2018/06/18 LogManager.GetLogger.PutLog(LogLevel.Information, "ImageCreateWorker::Execute(),开始") Do If errorCount >= Me._retryCount Then Dim message As String = String.Format("Worker处理发生错误。基准年:{0}、IJP:{1}", Me._kijunNen, Me._ijp) Dim newEx As FilingException = New FilingException(message, String.Empty) LogManager.GetLogger.PutLog(LogLevel.Error, newEx, String.Empty) Throw newEx End If '依次获取图像。 Using agent As New ImageCommandAgent agent.Kijun_nen = Me._kijunNen agent.HonpyoIJP = Me._ijp agent.IsRyomen = Me._isRyomen Using codec As New Codecs.RasterCodecs() ' 磁盘内存使用标志 codec.Options.Load.DiskMemory = Me._diskMemoryFlg Dim image As RasterImage = Nothing ' 2018/06/19 LogManager.GetLogger.PutLog(LogLevel.Information, "ImageCreateWorker::Execute() ExecuteReader,开始") Using dr As System.Data.Common.DbDataReader = agent.ExecuteReader(Me._dbConnection) ' 2018/06/19 LogManager.GetLogger.PutLog(LogLevel.Information, String.Format("ImageCreateWorker::Execute() ExecuteReader,结束,IJP:{0}", agent.HonpyoIJP)) Try While dr.Read() ' 2018/06/19 LogManager.GetLogger.PutLog(LogLevel.Information, "ImageCreateWorker::Execute() IMAGE_DATA MemoryStream,开始") Using ms As New IO.MemoryStream(DirectCast(dr("IMAGE_DATA"), Byte())), _ singleImage As RasterImage = codec.Load(ms) ' 2018/06/19 LogManager.GetLogger.PutLog(LogLevel.Information, String.Format("ImageCreateWorker::Execute() IMAGE_DATA MemoryStream,结束,IJP:{0}", agent.HonpyoIJP)) '此处抛出异常 Dim rotate As Short = DirectCast(dr("ROTATE"), Short) If rotate <> 0 Then ' 2018/06/19 LogManager.GetLogger.PutLog(LogLevel.Information, "ImageCreateWorker::Execute() Rotate,开始") Dim Rcommand As RotateCommand = New RotateCommand() Rcommand.Angle = rotate * 9000 Rcommand.Run(singleImage) ' 2018/06/19 LogManager.GetLogger.PutLog(LogLevel.Information, String.Format("ImageCreateWorker::Execute() Rotate,结束,IJP:{0}", agent.HonpyoIJP)) End If '转换为灰度后添加到主体。 ' 2018/06/19 LogManager.GetLogger.PutLog(LogLevel.Information, "ImageCreateWorker::Execute() Grayscale,开始") Dim command As New GrayscaleCommand() command.BitsPerPixel = 8 command.Run(singleImage) ' 2018/06/19 LogManager.GetLogger.PutLog(LogLevel.Information, String.Format("ImageCreateWorker::Execute() Grayscale,结束,IJP:{0}", agent.HonpyoIJP)) If image Is Nothing Then image = singleImage.CloneAll '第一张 Else ' 2018/06/19 LogManager.GetLogger.PutLog(LogLevel.Information, "ImageCreateWorker::Execute() AddPage,开始") image.AddPage(singleImage) '追加 ' 2018/06/19 LogManager.GetLogger.PutLog(LogLevel.Information, String.Format("ImageCreateWorker::Execute() AddPage,结束,IJP:{0}", agent.HonpyoIJP)) End If End Using End While Catch ex As System.Exception ' 异常结束 If Not image Is Nothing Then image.Dispose() image = Nothing End If Dim message As String = String.Format("【警告】表单图像获取失败。基准年:{0}、IJP:{1}", Me._kijunNen, Me._ijp) Dim newEx As FilingException = New FilingException(message, ex, String.Empty) LogManager.GetLogger.PutLog(LogLevel.Warning, newEx, String.Empty) LogManager.GetLogger.PutLog(LogLevel.Warning, ex.Message) LogManager.GetLogger.PutLog(LogLevel.Warning, ex.StackTrace) errorCount = errorCount + 1 Continue Do End Try End Using ' ■■ datareader ■■ Try ' 2018/06/19 LogManager.GetLogger.PutLog(LogLevel.Information, "ImageCreateWorker::Execute() 文件夹检索,开始") If Not System.IO.Directory.Exists(PathName) Then CreateDirectory(PathName) End If ' 2018/06/19 LogManager.GetLogger.PutLog(LogLevel.Information, String.Format("ImageCreateWorker::Execute() 文件夹检索,结束,IJP:{0}", agent.HonpyoIJP)) ' 2018/06/19 LogManager.GetLogger.PutLog(LogLevel.Information, "ImageCreateWorker::Execute() 文件检索,开始") If IO.File.Exists(FileFullPath) Then ' 由于save方法无法覆盖,先删除文件 IO.File.Delete(FileFullPath) End If ' 2018/06/19 LogManager.GetLogger.PutLog(LogLevel.Information, String.Format("ImageCreateWorker::Execute() 文件检索,结束,IJP:{0}", agent.HonpyoIJP)) ' 2018/06/19 LogManager.GetLogger.PutLog(LogLevel.Information, "ImageCreateWorker::Execute() 图像保存,开始") Select Case ImageMode Case "BINARY" '■■以二进制多页TIF保存时■■ codec.Save(image, FileFullPath, RasterImageFormat.CcittGroup4, 1) Case "BINARY-DITH" '' ■■指定抖动以二进制保存时■■ image.DitheringMethod = RasterDitheringMethod.FloydStein codec.Options.Save.UseImageDitheringMethod = True codec.Save(image, FileFullPath, RasterImageFormat.CcittGroup4, 1) Case "GRAY" '' ■■以灰度多页TIF保存时■■ codec.Options.Jpeg.Save.QualityFactor = 255 codec.Save(image, FileFullPath, RasterImageFormat.TifJpeg, 8) Case Else '' 其他情况,推荐以灰度保存。 codec.Options.Jpeg.Save.QualityFactor = 255 codec.Save(image, FileFullPath, RasterImageFormat.TifJpeg, 8) End Select ' 2018/06/19 LogManager.GetLogger.PutLog(LogLevel.Information, String.Format("ImageCreateWorker::Execute() 图像保存,结束,IJP:{0}", agent.HonpyoIJP)) Catch ex As System.Exception ' 异常结束 If Not image Is Nothing Then image.Dispose() image = Nothing End If Dim message As String = String.Format("【警告】图像文件输出失败。基准年:{0}、IJP:{1}", Me._kijunNen, Me._ijp) Dim newEx As FilingException = New FilingException(message, ex, String.Empty) LogManager.GetLogger.PutLog(LogLevel.Warning, newEx, String.Empty) LogManager.GetLogger.PutLog(LogLevel.Warning, ex.Message) LogManager.GetLogger.PutLog(LogLevel.Warning, ex.StackTrace) errorCount = errorCount + 1 Continue Do Finally If Not image Is Nothing Then image.Dispose() image = Nothing End If End Try ' 2018/06/18 LogManager.GetLogger.PutLog(LogLevel.Information, String.Format("ImageCreateWorker::Execute(),结束,IJP:{0}", Me._ijp)) Exit Do End Using ' codec End Using ' agent Loop ' 线程结束通知 ' 2019/11/03 加入try-catch捕获异常 'OnFinishedEventHandler(EventArgs.Empty) Try LogManager.GetLogger.PutLog(LogLevel.Information, "ImageCreateWorker::线程结束通知") OnFinishedEventHandler(EventArgs.Empty) Catch ex As System.Exception Dim message As String = "线程结束通知失败" Dim newEx As FilingException = New FilingException(message, ex, String.Empty) LogManager.GetLogger.PutLog(LogLevel.Warning, newEx, String.Empty) End Try End Sub
分析与解决方案
异常根源定位
从堆栈跟踪和出错代码来看,异常触发点是OracleDataReader的GetOrdinal方法,说明读取ROTATE列时存在以下问题:
- 数据层面:当前处理的数据库记录中,
ROTATE列不存在、列名大小写与代码中的"ROTATE"不匹配(Oracle默认区分大小写),或者列值为DBNull - DataReader状态异常:读取
IMAGE_DATA后执行codec.Load(ms)耗时过长,导致数据库连接超时、DataReader提前关闭,状态失效 - SQL语句问题:
ImageCommandAgent执行的SQL未包含ROTATE列,或列名拼写错误
排查与修复步骤
检查异常数据:
- 根据日志中的
IJP值,查询对应数据库记录,确认ROTATE列是否存在、列名大小写是否匹配,以及列值是否为DBNull - 若存在异常数据,临时修复或过滤该记录后重新执行任务
- 根据日志中的
验证数据库环境:
- 确认数据库连接正常,无临时中断、权限变更情况
- 检查
ImageCommandAgent中的SQL语句,确保包含ROTATE列且拼写正确
代码优化:
- 提前读取所有列值:避免长时间操作导致DataReader状态失效,先把需要的列值读取到本地变量再处理:
While dr.Read() ' 提前读取所有需要的列值 Dim imageData As Byte() = DirectCast(dr("IMAGE_DATA"), Byte()) Dim rotate As Short = If(dr.IsDBNull(dr.GetOrdinal("ROTATE")), 0, DirectCast(dr("ROTATE"), Short)) Using ms As New IO.MemoryStream(imageData), _ singleImage As RasterImage = codec.Load(ms) ' 后续处理逻辑不变 If rotate <> 0 Then ' 旋转操作 End If ' ...其他代码 End Using End While - 增加列存在性检查:避免因列名错误引发异常:
Dim rotateOrdinal As Integer Try rotateOrdinal = dr.GetOrdinal("ROTATE") Catch ex As IndexOutOfRangeException ' 列不存在时设默认值0 rotateOrdinal = -1 End If Dim rotate As Short = If(rotateOrdinal = -1 Or dr.IsDBNull(rotateOrdinal), 0, DirectCast(dr(rotateOrdinal), Short)) - 增强日志:记录当前处理记录的主键等标识,方便快速定位异常数据
- 提前读取所有列值:避免长时间操作导致DataReader状态失效,先把需要的列值读取到本地变量再处理:
内容的提问来源于stack exchange,提问作者Pathfinder
相关产品推荐
相关产品推荐

