ADO.NETが大型データを取得
3676 ワード
大規模なデータの取得
C#, Database, ASP.NET
DataReaderのデフォルトの動作は、データ行全体が使用可能になったときに、すぐに入力データを行形式でロードすることです.ただし、バイナリ・オブジェクト(BLOB)では、数十億バイトのデータが含まれている可能性があり、単一のローにこれほど多くのデータが含まれていないため、異なる処理が必要です.Command.ExecuteReaderメソッドには、リロードがあります.
CommandBehavior
パラメータを使用して、DataReaderのデフォルトの動作を変更します.CommandBehaviorをSequentialAccessはExecuteReaderメソッドに渡され、データ行をロードするのではなく、データを受信したときにデータ行をロードするようにデータReaderのデフォルトの動作を変更します.これは、BLOBやその他のビッグデータ構造をロードする理想的な方法です.この動作は、データ・ソースによって異なる場合があります.たとえば、Microsoft AccessからBLOBを返すと、受信したデータの順序でデータをロードするのではなく、BLOB全体がメモリにロードされます.DataReaderがSequentialAccessを使用するように設定されている場合は、返されるフィールドにアクセスする順序に注意してください.DataReaderのデフォルトの動作は、ロー全体が使用可能になったときにローをロードすることです.これにより、次のローを読み込む前に、返されたフィールドに任意の順序でアクセスできます.ただし、SequentialAccessを使用する場合は、DataReaderによって返される異なるフィールドに順次アクセスする必要があります.たとえば、クエリが3つのカラムを返し、3番目のカラムがBLOBである場合、3番目のフィールドのBLOBデータにアクセスする前に、1番目のフィールドと2番目のフィールドの値を返さなければなりません.最初のフィールドまたは2番目のフィールドにアクセスする前に3番目のフィールドにアクセスすると、最初のフィールドと2番目のフィールドの値は使用できなくなります.これは、SequentialAccessがDataReaderを変更し、データを順番に返すようにしたためであり、DataReaderが特定のデータを超えて読み込んだ場合、そのデータは使用できません.BLOBフィールドのデータにアクセスする場合は、配列にデータを埋め込むDataReaderのGetBytesまたはGetCharsタイプ化アクセサを使用します.文字データにGetStringを使用することもできますが、システムリソースを節約するために、BLOB値全体を単一の文字列変数にロードしたくない場合があります.返される特定のデータ・バッファ・サイズと、返されるデータから読み出される最初のバイトまたは文字の開始位置を指定できます.GetBytesおよびGetCharsは、返されるバイトまたは文字数を表すlong値を返します.空の配列がGetBytesまたはGetCharsに渡されると、BLOBの文字または文字の合計数が返されます.読み出したデータの開始位置として配列内のインデックスを指定できます.次の例では、Microsoft SQL Serverのpubsサンプル・データベースから発行者IDとバッジを返します.発行者ID(
C#, Database, ASP.NET
DataReaderのデフォルトの動作は、データ行全体が使用可能になったときに、すぐに入力データを行形式でロードすることです.ただし、バイナリ・オブジェクト(BLOB)では、数十億バイトのデータが含まれている可能性があり、単一のローにこれほど多くのデータが含まれていないため、異なる処理が必要です.Command.ExecuteReaderメソッドには、リロードがあります.
CommandBehavior
パラメータを使用して、DataReaderのデフォルトの動作を変更します.CommandBehaviorをSequentialAccessはExecuteReaderメソッドに渡され、データ行をロードするのではなく、データを受信したときにデータ行をロードするようにデータReaderのデフォルトの動作を変更します.これは、BLOBやその他のビッグデータ構造をロードする理想的な方法です.この動作は、データ・ソースによって異なる場合があります.たとえば、Microsoft AccessからBLOBを返すと、受信したデータの順序でデータをロードするのではなく、BLOB全体がメモリにロードされます.DataReaderがSequentialAccessを使用するように設定されている場合は、返されるフィールドにアクセスする順序に注意してください.DataReaderのデフォルトの動作は、ロー全体が使用可能になったときにローをロードすることです.これにより、次のローを読み込む前に、返されたフィールドに任意の順序でアクセスできます.ただし、SequentialAccessを使用する場合は、DataReaderによって返される異なるフィールドに順次アクセスする必要があります.たとえば、クエリが3つのカラムを返し、3番目のカラムがBLOBである場合、3番目のフィールドのBLOBデータにアクセスする前に、1番目のフィールドと2番目のフィールドの値を返さなければなりません.最初のフィールドまたは2番目のフィールドにアクセスする前に3番目のフィールドにアクセスすると、最初のフィールドと2番目のフィールドの値は使用できなくなります.これは、SequentialAccessがDataReaderを変更し、データを順番に返すようにしたためであり、DataReaderが特定のデータを超えて読み込んだ場合、そのデータは使用できません.BLOBフィールドのデータにアクセスする場合は、配列にデータを埋め込むDataReaderのGetBytesまたはGetCharsタイプ化アクセサを使用します.文字データにGetStringを使用することもできますが、システムリソースを節約するために、BLOB値全体を単一の文字列変数にロードしたくない場合があります.返される特定のデータ・バッファ・サイズと、返されるデータから読み出される最初のバイトまたは文字の開始位置を指定できます.GetBytesおよびGetCharsは、返されるバイトまたは文字数を表すlong値を返します.空の配列がGetBytesまたはGetCharsに渡されると、BLOBの文字または文字の合計数が返されます.読み出したデータの開始位置として配列内のインデックスを指定できます.次の例では、Microsoft SQL Serverのpubsサンプル・データベースから発行者IDとバッジを返します.発行者ID(
pub_id
)は文字フィールドであり、ロゴはグラフィック、すなわちBLOBである.logoフィールドはビットマップであるため、この例ではGetBytesを使用してバイナリデータを返します.フィールドに順番にアクセスする必要があるため、現在のデータ行の発行者IDには、バッジにアクセスする前にアクセスします.[C#] SqlConnection pubsConn = new SqlConnection("Data Source=localhost;Integrated Security=SSPI;Initial Catalog=pubs;"); SqlCommand logoCMD = new SqlCommand("SELECT pub_id, logo FROM pub_info", pubsConn); FileStream fs; //Writes the BLOB to a file (*.bmp). BinaryWriter bw; //Streams the BLOB to the FileStream object. int bufferSize = 100; //Size of the BLOB buffer. byte[] outbyte = new byte[bufferSize]; //The BLOB byte[] buffer to be filled by GetBytes. long retval; //The bytes returned from GetBytes. long startIndex = 0; //The starting position in the BLOB output. string pub_id = ""; //The publisher id to use in the file name. //Open the connection and read data into the DataReader. pubsConn.Open(); SqlDataReader myReader = logoCMD.ExecuteReader(CommandBehavior.SequentialAccess); while (myReader.Read()) { //Get the publisher id, which must occur before getting the logo. pub_id = myReader.GetString(0); //Create a file to hold the output. fs = new FileStream("logo"+ pub_id + ".bmp", FileMode.OpenOrCreate, FileAccess.Write); bw = new BinaryWriter(fs); //Reset the starting byte for the new BLOB. startIndex = 0; //Read the bytes into outbyte[] and retain the number of bytes returned. retval = myReader.GetBytes(1, startIndex, outbyte, 0, bufferSize); //Continue reading and writing while there are bytes beyond the size of the buffer. while (retval == bufferSize) { bw.Write(outbyte); bw.Flush(); //Reposition the start index to the end of the last buffer and fill the buffer. startIndex += bufferSize; retval = myReader.GetBytes(1, startIndex, outbyte, 0, bufferSize); } //Write the remaining buffer. bw.Write(outbyte, 0, (int)retval - 1); bw.Flush(); //Close the output file. bw.Close(); fs.Close(); } //Close the reader and the connection. myReader.Close(); pubsConn.Close();