2009-11-12 162 views
8

我想從數據庫中拉出一些二進制數據,並將它們寫入到pdf文件。在大多數情況下,這是順風順水,但偶爾的一排數據似乎會引發特定錯誤 -超時異常會導致SqlDataReader關閉?

超時已過期。操作完成之前超時的時間或服務器沒有響應。

請記住,這隻發生在少數幾行上,而且絕不是隨機的。相同的行總是拋出異常。我不太確定爲什麼拋出異常,但是我可以跳過那些會導致問題並繼續前進的行。但是,我的問題是,當我發現異常,然後嘗試移至下一行時,我遇到了另一個異常 -

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() 

回答

12

看起來您的SqlCommand超時 - 當您撥打ExecuteReader時,關聯的命令保持打開狀態,並且很容易超時,直到您完成閱讀。因爲它說的SqlCommand.CommandTimeout文檔中:

此屬性是累計 超時的 結果 命令執行或加工過程中的所有網絡讀取。在返回第一行後 仍然發生超時,而 不包括用戶處理時間, 只有網絡讀取時間。

當命令超時時,它將關閉無法恢復的閱讀器。

嘗試解決此問題的第一件事是大幅增加CommandTimeout,以確保可以繼續。

接下來,如果你還沒有這樣做的話,它可以幫助使用ExecuteReader重載允許你指定一個CommandBehavior,和(MSDN主題"Retrieving Large Data (ADO.NET)「在我們推薦的)通過CommandBehavior.SequentialAccess

最後,你也可以嘗試將讀取分成幾塊記錄

+0

事實證明,我所需要的只是增加超時(頭腦,你,我不得不將它增加到10分鐘左右)。提取是巨人!謝謝;) – Paulie 2009-11-12 03:09:39

1

如果SQL錯誤嚴重小於17,你可以設置SqlConnection.FireInfoMessageEventOnUserErrors = true來處理異常作爲警告。無論如何,大於嚴重程度17的任何事物都會到close the connection

相關問題