Condividi tramite


Recupero di dati binari

Per impostazione predefinita, il DataReader carica i dati in ingresso singolarmente come riga appena è disponibile un'intera riga di dati. Gli oggetti binari di grandi dimensioni (BLOB) richiedono tuttavia un trattamento diverso, perché possono contenere gigabyte di dati che non possono essere contenuti in una singola riga. Il metodo Command.ExecuteReader ha un overload che accetta un CommandBehavior argomento per modificare il comportamento predefinito di DataReader. È possibile passare SequentialAccess al ExecuteReader metodo per modificare il comportamento predefinito di DataReader in modo che invece di caricare righe di dati, i dati verranno caricati in sequenza man mano che vengono ricevuti. Questo è l'ideale per il caricamento di BLOB o altre strutture di dati di grandi dimensioni. Si noti che questo comportamento può dipendere dall'origine dati. Ad esempio, la restituzione di un BLOB da Microsoft Access caricherà l'intero BLOB caricato in memoria, anziché in sequenza durante la ricezione.

Quando si imposta DataReader per utilizzare SequentialAccess, è importante prestare attenzione alla sequenza in cui si accede ai campi restituiti. Il comportamento predefinito di DataReader, che carica un'intera riga non appena disponibile, consente di accedere ai campi restituiti in qualsiasi ordine fino a quando non viene letta la riga successiva. Quando si utilizza SequentialAccess, tuttavia, è necessario accedere ai campi restituiti dall'oggetto DataReader in ordine. Ad esempio, se la query restituisce tre colonne, la terza delle quali è un BLOB, è necessario restituire i valori del primo e del secondo campo prima di accedere ai dati BLOB nel terzo campo. Se si accede al terzo campo prima del primo o del secondo campo, i valori del primo e del secondo campo non sono più disponibili. Ciò è dovuto al fatto che SequentialAccess l'oggetto DataReader è stato modificato per restituire i dati in sequenza e i dati non sono disponibili dopo che l'oggetto DataReader è stato letto.

Quando si accede ai dati nel campo BLOB, usare le GetBytes funzioni di accesso digitate o GetChars di DataReader, che riempiono una matrice di dati. È anche possibile usare GetString per i dati di tipo carattere; tuttavia. per risparmiare risorse di sistema, è possibile che non si voglia caricare un intero valore BLOB in una singola variabile di stringa. È invece possibile specificare una dimensione del buffer specifica dei dati da restituire e una posizione iniziale per il primo byte o carattere da leggere dai dati restituiti. GetBytes e GetChars restituirà un long valore, che rappresenta il numero di byte o caratteri restituiti. Se si passa una matrice Null a GetBytes o GetChars, il valore long restituito sarà il numero totale di byte o caratteri nel BLOB. Facoltativamente, è possibile specificare un indice nella matrice come posizione iniziale per i dati letti.

Esempio

Nell'esempio seguente vengono restituiti l'ID editore e il logo del pubs database di esempio in Microsoft SQL Server. L'ID editore (pub_id) è un campo di carattere e il logo è un'immagine, che è un BLOB. Poiché il logo campo è una bitmap, l'esempio restituisce dati binari usando GetBytes. Si noti che l'ID editore è accessibile per la riga di dati corrente prima del logo, perché i campi devono essere accessibili in sequenza.

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

Vedere anche