2012-02-01 88 views
-1

這是參照:byte[] and efficiently passing by reference如何使用SqlDataReader重新填充字節數組?

而在這篇文章中發現的SqlDataReaderGetting binary data using SqlDataReader

裏面一個循環,我打電話數據庫,並返回一個大對象(varbinary[max])。目前,我遇到了OutOfMemory例外情況,所以我試圖減少大對象堆(LOH)中的佔用空間。

所以,我爲我下載的最大文件創建一個字節數組,並添加一些填充以防萬一。例如:

byte[] currentFile = new byte[largestFileSize * 1.1]; 

然後我通過這個currentFile數據庫方法。目前,我們使用的EnterpriseLibrary訪問數據庫:

DbCommand storedProcedure = MedicareDatabase.Db.GetStoredProcCommand(spName); 

storedProcedure.CommandTimeout = 5000; 

if (parameters != null) 
{ 
    foreach (Param parameter in parameters) 
    { 
     if (parameter != null) 
     { 
      MedicareDatabase.Db.AddInParameter(storedProcedure, parameter.ParameterName, parameter.DbType, parameter.Value); 
     } 
    } 
} 

try 
{ 
    BinaryWriter bw;      // Streams the BLOB to the FileStream object. 

    int bufferSize = 100;     // Size of the BLOB buffer. 
    byte[] outbyte = new byte[bufferSize]; // The BLOB byte[] buffer to be filled by GetBytes. 
    long retval;       // The bytes returned from GetBytes. 
    long startIndex = 0;     // The starting position in the BLOB output. 

    var myReader = MedicareDatabase.Db.ExecuteReader(storedProcedure); 

    while (myReader.Read()) 
    { 
     bw = new BinaryWriter(); 

     // Reset the starting byte for the new BLOB. 
     startIndex = 0; 

     // Read the bytes into outbyte[] and retain the number of bytes returned. 
     retval = myReader.GetBytes(1, startIndex, outbyte, 0, bufferSize); 

     // Continue reading and writing while there are bytes beyond the size of the buffer. 
     while (retval == bufferSize) 
     { 
      bw.Write(outbyte); 
      bw.Flush(); 

      // Reposition the start index to the end of the last buffer and fill the buffer. 
      startIndex += bufferSize; 
      retval = myReader.GetBytes(1, startIndex, outbyte, 0, bufferSize); 
     } 

     // Write the remaining buffer. 
     bw.Write(outbyte, 0, (int)retval - 1); 
     bw.Flush(); 

     // Close the output file. 
     bw.Close(); 
    } 

這是上面的第二篇文章中列出的代碼的修改。

這裏是我的問題(並隨時糾正我,如果我要問不同的問題)

  1. 你如何有效地補充了byte[]而無需創建一個新的對象?

  2. 上面的代碼不使用CommandBehavior.SequentialAccess這也是不需要創建一個新的對象。如何使用EnterpriseLibraryCommandBehavior s?

我打電話數據庫,並返回有byte[]陣列

更新

所以一段時間後,我決定手動填充字節數組。該參考文件現在已成功通過。

 SqlConnection pubsConn = null; 
     SqlCommand logoCMD = null; 
     SqlDataReader myReader = null; 

     try 
     { 
      pubsConn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["MedicareAccess"].ConnectionString); 
      logoCMD = new SqlCommand("esMD.proc_WS_SelectBiztalkBinary", pubsConn); 
      logoCMD.CommandType = CommandType.StoredProcedure; 

      SqlParameter submissionSetParamter = logoCMD.Parameters.Add("@submissionSetId", SqlDbType.UniqueIdentifier); 
      submissionSetParamter.Value = currentDocument.SubmissionSetId; 

      SqlParameter fileNameParam = logoCMD.Parameters.Add("@fileName", SqlDbType.VarChar, 100); 
      fileNameParam.Value = currentDocument.FullFileName; 


      int bufferSize = 100;     // Size of the BLOB buffer. 
      byte[] outbyte = new byte[bufferSize]; // The BLOB byte[] buffer to be filled by GetBytes. 
      long retval;       // The bytes returned from GetBytes. 
      long startIndex = 0;     // The starting position in the BLOB output. 

      // Open the connection and read data into the DataReader. 
      pubsConn.Open(); 
      myReader = logoCMD.ExecuteReader(CommandBehavior.SequentialAccess); 

      Array.Clear(data, 0, data.Length); 

      if (myReader == null) 
      { 
       return; 
      } 

      while (myReader.Read()) 
      { 
       currentDocument.Size = (int)myReader.GetBytes(0, 0, null, 0, 0); 
       int locationCounter = 0; 
       // Reset the starting byte for the new BLOB. 
       startIndex = 0; 

       // Read the bytes into outbyte[] and retain the number of bytes returned. 
       retval = myReader.GetBytes(0, startIndex, outbyte, 0, bufferSize); 

       // Continue reading and writing while there are bytes beyond the size of the buffer. 
       while (retval == bufferSize) 
       { 
        for (int i = 0; i < retval; i++) 
        { 
         data[locationCounter] = outbyte[i]; 
         locationCounter++; 
        } 

        // Reposition the start index to the end of the last buffer and fill the buffer. 
        startIndex += bufferSize; 
        retval = myReader.GetBytes(0, startIndex, outbyte, 0, bufferSize); 
       } 
      } 
     } 
     catch (Exception ex) 
     { 
      throw ex; 
     } 
     finally 
     { 
      if (myReader != null) 
      { 
       myReader.Dispose(); 
       myReader.Close(); 
       myReader = null; 
      } 

      if (pubsConn != null) 
      { 
       pubsConn.Dispose(); 
       pubsConn.Close(); 
       pubsConn = null; 
      } 
     } 

我敢肯定,有一種更有效的方式來寫這個。並沒有經過充分測試。但是參考文獻終於有效了。

+0

最後在那裏,當你說「*另外,你如何使用上面的讀者,以便它是*」...你有沒有留下什麼? – jadarnel27 2012-02-01 21:31:56

+0

刪除該行。這就是最終成爲問題2的原因。 – Cyfer13 2012-02-02 13:50:29

回答

0

所以我換下了主力While循環用下面的代碼:現在

  if (myReader.Read()) 
      { 
       currentDocument.Size = myReader.GetBytes(0, 0, null, 0, 0); 

       // Reset the starting byte for the new BLOB. 
       long startIndex = 0; 
       int bufferSize = 8196;     // Size of the BLOB buffer. 
       byte[] outbyte = new byte[bufferSize]; // The BLOB byte[] buffer to be filled by GetBytes. 
       long bytesInBuffer = 0;       // The bytes returned from GetBytes. 

       // Continue reading and writing while there are bytes beyond the size of the buffer. 
       while (startIndex < currentDocument.Size) 
       { 
        bytesInBuffer = myReader.GetBytes(0, startIndex, outbyte, 0, bufferSize); 
        Array.Copy(outbyte, 0, currentDocument.Data, startIndex, bytesInBuffer); 
        startIndex += bytesInBuffer; 
       } 
      } 

作品。