Dela via


Hämtar binära data

Som standard läser DataReader in inkommande data som en rad så snart en hel rad med data är tillgänglig. Binära stora objekt (BLOB) behöver dock olika behandling, eftersom de kan innehålla gigabyte data som inte kan ingå i en enda rad. Metoden Command.ExecuteReader har en överlagring som tar ett CommandBehavior argument för att ändra standardbeteendet för DataReader. Du kan skicka SequentialAccess till metoden ExecuteReader för att ändra standardbeteendet för DataReader så att data läses in sekventiellt i stället för att läsa in rader med data när de tas emot. Detta är idealiskt för inläsning av BLOB eller andra stora datastrukturer. Observera att det här beteendet kan bero på din datakälla. Om du till exempel returnerar en BLOB från Microsoft Access läses hela bloben in i minnet i stället för sekventiellt när den tas emot.

När du anger att DataReader ska använda SequentialAccess är det viktigt att notera sekvensen där du kommer åt fälten som returneras. Standardbeteendet för DataReader, som läser in en hel rad så snart den är tillgänglig, gör att du kan komma åt fälten som returneras i valfri ordning tills nästa rad har lästs. När du använder SequentialAccess måste du dock komma åt fälten som returneras av DataReader i ordning. Om frågan till exempel returnerar tre kolumner, varav den tredje är en BLOB, måste du returnera värdena för det första och andra fältet innan du kommer åt BLOB-data i det tredje fältet. Om du kommer åt det tredje fältet före det första eller andra fältet är värdena för det första och andra fältet inte längre tillgängliga. Det beror på att SequentialAccess har ändrat DataReader för att returnera data i följd och att data inte är tillgängliga när DataReader har läst förbi dem.

När du kommer åt data i BLOB-fältet använder du GetBytes - eller GetChars-typbehörigheterna för DataReader, som fyller en matris med data. Du kan också använda GetString för teckendata. för att spara systemresurser kanske du inte vill läsa in ett helt BLOB-värde i en enda strängvariabel. Du kan i stället ange en specifik buffertstorlek för data som ska returneras och en startplats för det första bytet eller tecknet som ska läsas från de returnerade data. GetBytes och GetChars returnerar ett long värde som representerar antalet byte eller tecken som returneras. Om du skickar en null-matris till GetBytes eller GetChars blir det långa värdet som returneras det totala antalet byte eller tecken i BLOB. Du kan också ange ett index i matrisen som en startposition för de data som läss.

Exempel

I följande exempel returneras utgivar-ID:t och logotypen från pubs-exempeldatabasen i Microsoft SQL Server. Utgivar-ID :t (pub_id) är ett teckenfält och logotypen är en bild, som är en BLOB. Eftersom logotypfältet är en bitmapp returnerar exemplet binära data med hjälp av GetBytes. Observera att utgivar-ID:t används för den aktuella dataraden före logotypen, eftersom fälten måste nås sekventiellt.

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

Se även