Recupero di dati binariRetrieving Binary Data

Per impostazione predefinita, il DataReader Carica dati in arrivo come una riga non appena è disponibile un'intera riga di dati.By default, the DataReader loads incoming data as a row as soon as an entire row of data is available. Tuttavia, è necessario gestire gli oggetti BLOB (Binary Large Object, oggetto binario di grandi dimensioni) in modo diverso, poiché è possibile che contengano gigabyte di dati che non possono risiedere in una sola riga.Binary large objects (BLOBs) need different treatment, however, because they can contain gigabytes of data that cannot be contained in a single row. Il Command. ExecuteReader metodo presenta un overload che accetta un CommandBehavior argomento per modificare il comportamento predefinito del DataReader.The Command.ExecuteReader method has an overload that will take a CommandBehavior argument to modify the default behavior of the DataReader. È possibile passare SequentialAccess per il ExecuteReader metodo per modificare il comportamento predefinito del DataReader in modo che, invece di caricare righe di dati, carichi i dati in modo sequenziale non appena viene ricevuto.You can pass SequentialAccess to the ExecuteReader method to modify the default behavior of the DataReader so that instead of loading rows of data, it will load data sequentially as it is received. Si consiglia di usare questa procedura per caricare BLOB o altre strutture di dati di grandi dimensioni.This is ideal for loading BLOBs or other large data structures. Notare che questo comportamento può variare a seconda dell'origine dati.Note that this behavior may depend on your data source. La restituzione di un BLOB da Microsoft Access comporta, ad esempio, il caricamento in memoria dell'intero BLOB, anziché il caricamento sequenziale durante la ricezione.For example, returning a BLOB from Microsoft Access will load the entire BLOB being loaded into memory, rather than sequentially as it is received.

Quando si imposta la DataReader utilizzare SequentialAccess, è importante notare la sequenza in cui si accede ai campi restituiti.When setting the DataReader to use SequentialAccess, it is important to note the sequence in which you access the fields returned. Il comportamento predefinito del 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.The default behavior of the DataReader, which loads an entire row as soon as it is available, allows you to access the fields returned in any order until the next row is read. Quando si utilizza SequentialAccess , tuttavia, è necessario accedere ai campi restituiti dal DataReader in ordine.When using SequentialAccess however, you must access the fields returned by the DataReader in order. Ad esempio, se la query restituisce tre colonne, di cui la terza è un BLOB, è necessario restituire i valori del primo e del secondo campo prima di accedere ai dati BLOB nel terzo campo.For example, if your query returns three columns, the third of which is a BLOB, you must return the values of the first and second fields before accessing the BLOB data in the third field. Se si accede al terzo campo prima del primo o del secondo, i valori del primo o del secondo campo non saranno più disponibili.If you access the third field before the first or second fields, the first and second field values are no longer available. Infatti SequentialAccess è modificato il DataReader per restituire dati in sequenza e i dati non è disponibile dopo il DataReader stati letti.This is because SequentialAccess has modified the DataReader to return data in sequence and the data is not available after the DataReader has read past it.

Quando l'accesso ai dati nel campo BLOB, utilizzare il GetBytes o GetChars funzioni di accesso tipizzate di DataReader, quale compilare una matrice con i dati.When accessing the data in the BLOB field, use the GetBytes or GetChars typed accessors of the DataReader, which fill an array with data. È inoltre possibile utilizzare GetString per dati di tipo carattere; tuttavia.You can also use GetString for character data; however. è probabile che per risparmiare risorse di sistema si preferisca non caricare un intero valore BLOB in un'unica variabile di stringa.to conserve system resources you might not want to load an entire BLOB value into a single string variable. È possibile invece specificare una determinata dimensione del buffer da restituire e una posizione iniziale per il primo byte o carattere da leggere dai dati restituiti.You can instead specify a specific buffer size of data to be returned, and a starting location for the first byte or character to be read from the returned data. GetBytes e GetChars restituirà un long valore, che rappresenta il numero di byte o caratteri restituiti.GetBytes and GetChars will return a long value, which represents the number of bytes or characters returned. Se si passa una matrice null a GetBytes o GetChars, il valore long restituito corrisponderà al numero totale di byte o caratteri del BLOB.If you pass a null array to GetBytes or GetChars, the long value returned will be the total number of bytes or characters in the BLOB. Facoltativamente, è possibile specificare un indice nella matrice come posizione iniziale per i dati che vengono letti.You can optionally specify an index in the array as a starting position for the data being read.

EsempioExample

L'esempio seguente restituisce l'ID dell'editore e il logo dal pubs database di esempio in Microsoft SQL Server.The following example returns the publisher ID and logo from the pubs sample database in Microsoft SQL Server. L'identificatore dell'editore (pub_id) è un campo di testo è il logo è un'immagine, quindi un BLOB.The publisher ID (pub_id) is a character field, and the logo is an image, which is a BLOB. Poiché il logo è una bitmap, nell'esempio vengono restituiti dati binari utilizzando GetBytes.Because the logo field is a bitmap, the example returns binary data using GetBytes. Notare che all'identificatore dell'editore nella riga corrente di dati si accede prima del logo, in quanto i campi devono essere letti in modo sequenziale.Notice that the publisher ID is accessed for the current row of data before the logo, because the fields must be accessed sequentially.

' 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 ancheSee Also

Utilizzo di DataReaderWorking with DataReaders
Dati binari e con valori elevati SQL ServerSQL Server Binary and Large-Value Data
Provider gestiti ADO.NET e Centro per sviluppatori di set di datiADO.NET Managed Providers and DataSet Developer Center