Bináris adatok beolvasása
A DataReader alapértelmezés szerint sorként tölti be a bejövő adatokat, amint egy teljes adatsor elérhető. A bináris nagyméretű objektumoknak (BLOB-knak) azonban eltérő kezelésre van szükségük, mivel gigabájtnyi adatot tartalmazhatnak, amelyek egyetlen sorban nem tárolhatók. A Command.ExecuteReader metódus túlterheléssel rendelkezik, amely argumentumot CommandBehavior használ a DataReader alapértelmezett viselkedésének módosításához. Az ExecuteReader metódusnak továbbítva SequentialAccess módosíthatja a DataReader alapértelmezett viselkedését, így az adatsorok betöltése helyett az adatok egymás után töltődnek be a beérkezéskor. Ez ideális blobok vagy más nagy adatstruktúrák betöltéséhez. Vegye figyelembe, hogy ez a viselkedés az adatforrástól függhet. Ha például egy BLOB-t ad vissza a Microsoft Accessből, az a teljes, a memóriába betöltött BLOB-t tölti be a fogadási sorrend helyett.
Amikor a DataReadert a SequentialAccess használatára állítja, fontos megjegyezni, hogy milyen sorrendben éri el a visszaadott mezőket. A DataReader alapértelmezett viselkedése, amely amint elérhető, betölt egy teljes sort, lehetővé teszi a visszaadott mezők bármilyen sorrendben való elérését a következő sor beolvasásáig. A SequentialAccess használatakor azonban a DataReader által visszaadott mezőket sorrendben kell elérnie. Ha például a lekérdezés három oszlopot ad vissza, amelyek közül a harmadik blob, akkor az első és a második mező értékeit kell visszaadnia, mielőtt hozzáfér a blobadatokhoz a harmadik mezőben. Ha a harmadik mezőt az első vagy a második mező előtt éri el, az első és a második mező értéke már nem érhető el. Ennek az az oka, hogy a SequentialAccess úgy módosította a DataReadert , hogy egymás után adja vissza az adatokat, és az adatok nem érhetők el, miután a DataReader átolvasott rajta.
A BLOB mező adatainak elérésekor használja a DataReader GetBytes vagy GetChars típusú tartozékait, amelyek egy tömböt töltenek ki adatokkal. Karakteradatokhoz használhatja a GetStringet is. a rendszererőforrások megőrzése érdekében előfordulhat, hogy nem szeretne egy teljes BLOB-értéket betölteni egyetlen sztringváltozóba. Ehelyett megadhat egy adott pufferméretet a visszaadni kívánt adatoknak, valamint a visszaadott adatokból beolvasandó első bájt vagy karakter kezdő helyét. A GetBytes és a GetChars egy long
értéket ad vissza, amely a visszaadott bájtok vagy karakterek számát jelöli. Ha null tömböt ad át a GetBytes vagy a GetChars számára, a visszaadott hosszú érték a BLOB bájtjainak vagy karaktereinek teljes száma lesz. Tetszés szerint megadhat egy indexet a tömbben az éppen beolvasott adatok kiindulási helyeként.
Példa
Az alábbi példa a közzétevő azonosítóját és emblémáját adja vissza a Microsoft SQL Server pubs mintaadatbázisából. A közzétevő azonosítója (pub_id
) egy karaktermező, az embléma pedig egy kép, amely egy BLOB. Mivel az emblémamező bitkép, a példa bináris adatokat ad vissza a GetBytes használatával. Figyelje meg, hogy a közzétevő azonosítója az aktuális adatsorhoz fér hozzá az embléma előtt, mert a mezőket egymás után kell elérni.
' 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();