Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
По умолчанию DataReader входящие данные загружаются в виде строки, как только доступна вся строка данных. Однако двоичные большие объекты (BLOB-объекты) требуют другого лечения, так как они могут содержать гигабайты данных, которые не могут содержаться в одной строке. Метод Command.ExecuteReader имеет перегрузку, которая принимает CommandBehavior аргумент для изменения поведения по умолчанию DataReader. Можно передать SequentialAccessExecuteReader методу, чтобы изменить поведение DataReader по умолчанию таким образом, чтобы вместо загрузки строк данных он загрузит данные последовательно по мере получения. Это идеально подходит для загрузки BLOB-объектов или других крупных структур данных. Обратите внимание, что это поведение может зависеть от источника данных. Например, при возврате BLOB-объекта из Microsoft Access весь BLOB будет загружен в память сразу, а не последовательно по мере получения.
При настройке DataReader для использования SequentialAccess важно учитывать последовательность, в которой вы получаете доступ к возвращаемым полям. Поведение dataReader по умолчанию, которое загружает всю строку сразу после его доступности, позволяет получить доступ к полям, возвращаемым в любом порядке, пока следующая строка не будет прочитана. Однако при использовании SequentialAccess необходимо получить доступ к полям, возвращаемым порядком DataReader . Например, если ваш запрос возвращает три столбца, третий из которых — это BLOB, сначала необходимо вернуть значения первых двух полей перед доступом к данным BLOB в третьем поле. Если вы обращаетесь к третьему полю перед первым или вторым полями, значения первого и второго полей больше не доступны. Это связано с тем, что SequentialAccess изменил DataReader, чтобы данные возвращались по порядку, и данные недоступны после того, как DataReader их прочитал.
При доступе к данным в поле BLOB используйте GetBytes или GetChars типизированные методы доступа DataReader, которые заполняют массив данными. Кроме того, можно использовать GetString для символьных данных. Чтобы сохранить системные ресурсы, может потребоваться не загрузить целое значение BLOB в одну строковую переменную. Вместо этого можно указать определенный размер возвращаемых данных буфера и начальное расположение для первого байта или символа, считываемого из возвращаемых данных.
GetBytes и GetChars возвращают long числовое значение, представляющее количество возвращаемых байтов или символов. Если вы передаете нулевой массив в GetBytes или GetChars, возвращаемое длинное значение будет общим количеством байтов или символов в BLOB. При необходимости можно указать индекс в массиве в качестве начальной позиции для считываемых данных.
Пример
В следующем примере возвращается идентификатор издателя и логотип из pubs образца базы данных в Microsoft SQL Server. Идентификатор издателя (pub_id) — это символьное поле, а логотип — это изображение, которое является BLOB.
logo Так как поле является растровым изображением, в примере возвращаются двоичные данные с помощью GetBytes. Обратите внимание, что к идентификатору издателя получают доступ для текущей строки данных перед логотипом, так как доступ к полям должен осуществляться последовательно.
' 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();