Partilhar via


Recuperando dados binários

Por padrão, o DataReader carrega dados de entrada como uma linha assim que uma linha inteira de dados está disponível. No entanto, objetos binários grandes (BLOBs) precisam de tratamento diferente, porque podem conter gigabytes de dados que não podem ser contidos em uma única linha. O método Command.ExecuteReader tem uma sobrecarga que usará um CommandBehavior argumento para modificar o comportamento padrão do DataReader. Você pode passar SequentialAccess para o método ExecuteReader para modificar o comportamento padrão do DataReader para que, em vez de carregar linhas de dados, ele carregue os dados sequencialmente à medida que são recebidos. Isso é ideal para carregar BLOBs ou outras grandes estruturas de dados. Observe que esse comportamento pode depender da sua fonte de dados. Por exemplo, retornar um BLOB do Microsoft Access carregará todo o BLOB que está sendo carregado na memória, em vez de sequencialmente como ele é recebido.

Ao definir o DataReader para usar SequentialAccess, é importante observar a sequência na qual você acessa os campos retornados. O comportamento padrão do DataReader, que carrega uma linha inteira assim que ela está disponível, permite que você acesse os campos retornados em qualquer ordem até que a próxima linha seja lida. Ao usar SequentialAccess , no entanto, você deve acessar os campos retornados pelo DataReader em ordem. Por exemplo, se sua consulta retornar três colunas, a terceira das quais é um BLOB, você deve retornar os valores do primeiro e segundo campos antes de acessar os dados BLOB no terceiro campo. Se você acessar o terceiro campo antes do primeiro ou segundo campos, os valores do primeiro e do segundo campo não estarão mais disponíveis. Isso ocorre porque o SequentialAccess modificou o DataReader para retornar dados em sequência e os dados não estão disponíveis depois que o DataReader leu além dele.

Ao acessar os dados no campo BLOB, use os acessadores digitados GetBytes ou GetChars do DataReader, que preenchem uma matriz com dados. No entanto, você também pode usar GetString para dados de caracteres. para conservar os recursos do sistema, talvez você não queira carregar um valor BLOB inteiro em uma única variável de cadeia de caracteres. Em vez disso, você pode especificar um tamanho de buffer específico dos dados a serem retornados e um local inicial para o primeiro byte ou caractere a ser lido dos dados retornados. GetBytes e GetChars retornarão um long valor, que representa o número de bytes ou caracteres retornados. Se você passar uma matriz nula para GetBytes ou GetChars, o valor longo retornado será o número total de bytes ou caracteres no BLOB. Opcionalmente, você pode especificar um índice na matriz como uma posição inicial para os dados que estão sendo lidos.

Exemplo

O exemplo a seguir retorna a ID do editor e o logotipo do banco de dados de exemplo pubs no Microsoft SQL Server. O ID do editor (pub_id) é um campo de caractere e o logotipo é uma imagem, que é um BLOB. Como o campo de logotipo é um bitmap, o exemplo retorna dados binários usando GetBytes. Observe que o ID do editor é acessado para a linha atual de dados antes do logotipo, porque os campos devem ser acessados sequencialmente.

' Assumes that connection is a valid SqlConnection object.  
Dim command As SqlCommand = New SqlCommand( _  
  "SELECT pub_id, logo FROM pub_info", connection)  
  
' Writes the BLOB to a file (*.bmp).  
Dim stream As FileStream
' Streams the binary data to the FileStream object.  
Dim writer As BinaryWriter
' The size of the BLOB buffer.  
Dim bufferSize As Integer = 100
' The BLOB byte() buffer to be filled by GetBytes.  
Dim outByte(bufferSize - 1) As Byte
' The bytes returned from GetBytes.  
Dim retval As Long
' The starting position in the BLOB output.  
Dim startIndex As Long = 0
  
' The publisher id to use in the file name.  
Dim pubID As String = ""
  
' Open the connection and read data into the DataReader.  
connection.Open()  
Dim reader As SqlDataReader = command.ExecuteReader(CommandBehavior.SequentialAccess)  
  
Do While reader.Read()  
  ' Get the publisher id, which must occur before getting the logo.  
  pubID = reader.GetString(0)  
  
  ' Create a file to hold the output.  
  stream = New FileStream( _  
    "logo" & pubID & ".bmp", FileMode.OpenOrCreate, FileAccess.Write)  
  writer = New BinaryWriter(stream)  
  
  ' Reset the starting byte for a new BLOB.  
  startIndex = 0  
  
  ' Read bytes into outByte() and retain the number of bytes returned.  
  retval = reader.GetBytes(1, startIndex, outByte, 0, bufferSize)  
  
  ' Continue while there are bytes beyond the size of the buffer.  
  Do While retval = bufferSize  
    writer.Write(outByte)  
    writer.Flush()  
  
    ' Reposition start index to end of the last buffer and fill buffer.  
    startIndex += bufferSize  
    retval = reader.GetBytes(1, startIndex, outByte, 0, bufferSize)  
  Loop  
  
  ' Write the remaining buffer.  
  writer.Write(outByte, 0 , retval - 1)  
  writer.Flush()  
  
  ' Close the output file.  
  writer.Close()  
  stream.Close()  
Loop  
  
' Close the reader and the connection.  
reader.Close()  
connection.Close()  
// Assumes that connection is a valid SqlConnection object.  
SqlCommand command = new SqlCommand(  
  "SELECT pub_id, logo FROM pub_info", connection);  
  
// Writes the BLOB to a file (*.bmp).  
FileStream stream;
// Streams the BLOB to the FileStream object.  
BinaryWriter writer;
  
// Size of the BLOB buffer.  
int bufferSize = 100;
// The BLOB byte[] buffer to be filled by GetBytes.  
byte[] outByte = new byte[bufferSize];
// The bytes returned from GetBytes.  
long retval;
// The starting position in the BLOB output.  
long startIndex = 0;
  
// The publisher id to use in the file name.  
string pubID = "";
  
// Open the connection and read data into the DataReader.  
connection.Open();  
SqlDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess);  
  
while (reader.Read())  
{  
  // Get the publisher id, which must occur before getting the logo.  
  pubID = reader.GetString(0);
  
  // Create a file to hold the output.  
  stream = new FileStream(  
    "logo" + pubID + ".bmp", FileMode.OpenOrCreate, FileAccess.Write);  
  writer = new BinaryWriter(stream);  
  
  // Reset the starting byte for the new BLOB.  
  startIndex = 0;  
  
  // Read bytes into outByte[] and retain the number of bytes returned.  
  retval = reader.GetBytes(1, startIndex, outByte, 0, bufferSize);  
  
  // Continue while there are bytes beyond the size of the buffer.  
  while (retval == bufferSize)  
  {  
    writer.Write(outByte);  
    writer.Flush();  
  
    // Reposition start index to end of last buffer and fill buffer.  
    startIndex += bufferSize;  
    retval = reader.GetBytes(1, startIndex, outByte, 0, bufferSize);  
  }  
  
  // Write the remaining buffer.  
  writer.Write(outByte, 0, (int)retval);  
  writer.Flush();  
  
  // Close the output file.  
  writer.Close();  
  stream.Close();  
}  
  
// Close the reader and the connection.  
reader.Close();  
connection.Close();  

Consulte também