如何使用SqlDataReader重新填充字节数组?

这是参考: byte []并通过引用有效传递

并且在这篇文章中找到了SqlDataReader : 使用SqlDataReader获取二进制数据

在循环中,我正在调用数据库并返回一个大对象( varbinary[max] )。 目前,我OutOfMemoryexception,所以我试图减少大对象堆(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一起使用?

我正在调用数据库并返回一个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; } } 

我确信有一种更有效的方式来写这个。 并没有经过全面测试。 但参考终于有效了。

所以我用以下代码替换了主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; } } 

现在工作。