2009-11-12 5 views
8

J'essaie d'extraire des données binaires d'une base de données et de les écrire dans des fichiers pdf. Pour la plupart, cela se passe le long de la baignade, mais la rangée de données occasionnelle semble jeter une erreur particulière -Une exception de délai d'attente provoque la fermeture de SqlDataReader?

Expiration du délai. Le délai d'expiration s'est écoulé avant la fin de l'opération ou le serveur ne répond pas. Gardez à l'esprit que cela ne se produit que sur une poignée de lignes, et n'est jamais aléatoire.

Les mêmes lignes lèvent toujours l'exception. Je ne suis pas vraiment sûr pourquoi l'exception est levée, mais je suis d'accord pour sauter les lignes qui causent des problèmes et passer à autre chose. Mon problème, cependant, est que lorsque j'attrape l'exception et que j'essaie de passer à la ligne suivante, je rencontre une autre exception -

InvalidOperationException - Tentative non valide d'appel Lire lorsque le lecteur est fermé.

Cela signifie-t-il que le lecteur se ferme automatiquement dès qu'il rencontre une exception? Comment pourrais-je aller au prochain rang sans drames?

 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); 
      } 
     } 

trace de la pile, comme l'a demandé -

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

Répondre

12

Il semble que votre SqlCommand expire - lorsque vous appelez ExecuteReader, la commande associée reste ouverte et sera vulnérable aux délais d'attente jusqu'à ce que vous ayez fini de lire. Comme il est dit dans la documentation SqlCommand.CommandTimeout:

Cette propriété est le cumulatif de temps pour tout le réseau se lit lors de l'exécution de la commande ou le traitement des résultats. Un délai peut toujours se produire après le retour de la première ligne et n'inclut pas le temps de traitement de l'utilisateur, uniquement le temps de lecture réseau.

Lorsque la commande expire, il ferme le lecteur, dont vous ne pouvez pas récupérer.

La première chose à essayer de résoudre ceci est d'augmenter considérablement le CommandTimeout, juste pour vous assurer que vous pouvez continuer.

Ensuite, si vous ne l'avez pas déjà fait, il peut être utile d'utiliser la surcharge ExecuteReader qui vous permet de spécifier un CommandBehavior et passer CommandBehavior.SequentialAccess (par la recommandation dans le sujet MSDN "Retrieving Large Data (ADO.NET) «).

Enfin, vous pouvez également essayer de décomposer les lectures en blocs d'enregistrements

+0

Il s'est avéré que tout ce dont j'avais besoin était d'augmenter le délai d'attente (attention, je devais l'augmenter à environ 10 minutes). suis extraire sont géants! Merci;) – Paulie

1

Si l'erreur SQL gravité est inférieur à 17, vous pouvez définir SqlConnection.FireInfoMessageEventOnUserErrors = true pour gérer l'exception d'avertissement. Tout ce qui est supérieur à la gravité 17 va à close the connection, peu importe quoi.