我正在尝试从数据库中提取一些二进制数据并将其写入pdf文件。在大多数情况下,这进展顺利,但偶尔出现的数据行似乎会引发特定错误-
超时时间已到。在操作完成之前超时或服务器没有响应。
请记住,这仅在少数几行上发生,并且绝不是随机的。相同的行始终会引发异常。我不太确定为什么会引发异常,但是我可以跳过确实引起问题的行并继续前进。但是,我的问题是,当我捕获到异常然后尝试移至下一行时,我遇到了另一个异常-
InvalidOperationException-当关闭阅读器时,尝试调用Read的无效尝试。
这是否意味着读取器在遇到异常后会自动关闭?我将如何在没有任何戏剧的情况下继续进行下一行?
while (sdrReader.Read()) // Second exception happens here { try { byte[] byteData = new Byte[(sdrReader.GetBytes(0, 0, null, 0, int.MaxValue))]; // first exception happens here sdrReader.GetBytes(0, 0, byteData, 0, byteData.Length); string strOutputFileName = sdrReader.GetInt32(1).ToString() + ".pdf"; msMemoryStreams = new MemoryStream(); msMemoryStreams.Write(byteData, 0, byteData.Length); byte[] byteArray = msMemoryStreams.ToArray(); msMemoryStreams.Flush(); msMemoryStreams.Close(); writeByteArrayToFile(byteData, txtFilesPath.Text + "\\" + strOutputFileName); } catch (Exception e) { Logger.Write("Document failed to convert: " + e.Message); } }
根据要求进行堆栈跟踪-
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj) at System.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject stateObj, UInt32 error) at System.Data.SqlClient.TdsParserStateObject.ReadSni(DbAsyncResult asyncResult, TdsParserStateObject stateObj) at System.Data.SqlClient.TdsParserStateObject.ReadNetworkPacket() at System.Data.SqlClient.TdsParserStateObject.ReadBuffer() at System.Data.SqlClient.TdsParserStateObject.ReadByteArray(Byte[] buff, Int32 offset, Int32 len) at System.Data.SqlClient.TdsParser.ReadSqlValue(SqlBuffer value, SqlMetaDataPriv md, Int32 length, TdsParserStateObject stateObj) at System.Data.SqlClient.SqlDataReader.ReadColumnData() at System.Data.SqlClient.SqlDataReader.ReadColumn(Int32 i, Boolean setTimeout) at System.Data.SqlClient.SqlDataReader.GetSqlBinary(Int32 i) at System.Data.SqlClient.SqlDataReader.GetBytesInternal(Int32 i, Int64 dataIndex, Byte[] buffer, Int32 bufferIndex, Int32 length) at System.Data.SqlClient.SqlDataReader.GetBytes(Int32 i, Int64 dataIndex, Byte[] buffer, Int32 bufferIndex, Int32 length) at Pdf2Rtf.Form1.Read() in F:\Code\Pdf2Rtf\Pdf2Rtf\Pdf2Rtf\Form1.cs:line 77 at Pdf2Rtf.Form1.btnRead_Click(Object sender, EventArgs e) in F:\Code\Pdf2Rtf\Pdf2Rtf\Pdf2Rtf\Form1.cs:line 24 at System.Windows.Forms.Control.OnClick(EventArgs e) at System.Windows.Forms.Button.OnClick(EventArgs e) at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.ButtonBase.WndProc(Message& m) at System.Windows.Forms.Button.WndProc(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg) at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData) at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context) at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context) at System.Windows.Forms.Application.Run(Form mainForm) at Pdf2Rtf.Program.Main() in F:\Code\Pdf2Rtf\Pdf2Rtf\Pdf2Rtf\Program.cs:line 18 at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart()
看来您SqlCommand正在超时- 当您调用时ExecuteReader,关联的命令将保持打开状态,并且容易受到超时的影响,直到您完成阅读为止。如SqlCommand.CommandTimeout文档中所述:
SqlCommand
ExecuteReader
SqlCommand.CommandTimeout
此属性是命令执行或结果处理期间所有网络读取的累积超时。返回第一行后仍然可能发生超时,并且不包括用户处理时间,仅包括网络读取时间。
当命令超时时,它将关闭读取器,您无法从该读取器中恢复。
尝试解决此问题的第一件事就是CommandTimeout大幅增加功能,只是确保您可以继续进行。
CommandTimeout
接下来,如果尚未这样做,则可以使用ExecuteReader允许您指定重载CommandBehavior并传递的重载CommandBehavior.SequentialAccess(根据MSDN主题“检索大数据(ADO.NET) ”中的建议)。
CommandBehavior
CommandBehavior.SequentialAccess
最后,您也可以尝试将读取结果分成多个记录块。