Pobieranie danych binarnych
Domyślnie element DataReader ładuje dane przychodzące, gdy tylko cały wiersz danych jest dostępny. Duże obiekty binarne (BLOB) wymagają jednak innego traktowania, ponieważ mogą zawierać gigabajty danych, których nie można znaleźć w jednym wierszu. Metoda Command.ExecuteReader ma przeciążenie, które spowoduje CommandBehavior zmianę domyślnego zachowania elementu DataReader. Możesz przekazać SequentialAccess do metody ExecuteReader , aby zmodyfikować domyślne zachowanie elementu DataReader , aby zamiast ładować wiersze danych, dane będą ładowane sekwencyjnie w miarę ich odbierania. Jest to idealne rozwiązanie do ładowania obiektów BLOB lub innych dużych struktur danych. Należy pamiętać, że to zachowanie może zależeć od źródła danych. Na przykład zwrócenie obiektu BLOB z programu Microsoft Access spowoduje załadowanie całego obiektu BLOB do pamięci, a nie sekwencyjnie, gdy jest odbierany.
Podczas ustawiania elementu DataReader do używania funkcji SequentialAccess należy zwrócić uwagę na sekwencję, w której uzyskujesz dostęp do zwracanych pól. Domyślne zachowanie elementu DataReader, które ładuje cały wiersz zaraz po udostępnieniu, umożliwia dostęp do pól zwracanych w dowolnej kolejności do momentu odczytania następnego wiersza. Jednak w przypadku korzystania z funkcji SekwencyjnejAccess należy uzyskać dostęp do pól zwracanych przez element DataReader w kolejności. Jeśli na przykład zapytanie zwraca trzy kolumny, z których trzeci jest obiektem BLOB, przed uzyskaniem dostępu do danych obiektu BLOB w trzecim polu należy zwrócić wartości pierwszych i drugich pól. Jeśli uzyskujesz dostęp do trzeciego pola przed pierwszym lub drugim polem, wartości pierwszego i drugiego pola nie będą już dostępne. Dzieje się tak dlatego, że funkcja SekwencjonalizacjiAccess zmodyfikowała element DataReader w celu zwrócenia danych w sekwencji, a dane nie są dostępne po odczytaniu elementu DataReader w przeszłości.
Podczas uzyskiwania dostępu do danych w polu OBIEKTU BLOB użyj metod dostępu typu GetBytes lub GetChars elementu DataReader, które wypełniają tablicę danymi. Można również użyć funkcji GetString dla danych znaków. aby zaoszczędzić zasoby systemowe, możesz nie chcieć załadować całej wartości obiektu BLOB do pojedynczej zmiennej ciągu. Zamiast tego można określić określony rozmiar buforu danych, który ma zostać zwrócony, oraz lokalizację początkową pierwszego bajtu lub znaku, który ma zostać odczytany z zwracanych danych. Funkcja GetBytes i GetChars zwróci wartość reprezentującą long
liczbę zwracanych bajtów lub znaków. Jeśli przekażesz tablicę o wartości null do funkcji GetBytes lub GetChars, zwracana długa wartość będzie całkowitą liczbą bajtów lub znaków w obiekcie BLOB. Opcjonalnie możesz określić indeks w tablicy jako pozycję początkową dla odczytywanych danych.
Przykład
Poniższy przykład zwraca identyfikator wydawcy i logo z przykładowej bazy danych pubs w programie Microsoft SQL Server. Identyfikator wydawcy (pub_id
) jest polem znaków, a logo jest obrazem, który jest obiektem BLOB. Ponieważ pole logo jest mapą bitową, przykład zwraca dane binarne przy użyciu funkcji GetBytes. Zwróć uwagę, że identyfikator wydawcy jest dostępny dla bieżącego wiersza danych przed logo, ponieważ pola muszą być uzyskiwane sekwencyjnie.
' 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();