web-dev-qa-db-ja.com

SqlDataReader.GetBytes()に渡す必要のある「長さ」パラメーター

SqlDataReaderがあり、SqlDataReader.GetBytes()メソッドを使用してそこからvarbinary(max)列を読み取る必要があります。このメソッドはバイト配列にデータを入力するため、読み取るデータの長さを知る必要があります。

これは私が混乱するところです..明らかに、この行/列でデータベースから返されたすべてのデータを読み取りたいので、どの「長さ」パラメーターを渡す必要がありますか?

私が見る限り、SqlDataReaderは、使用可能なデータの長さを検出するためのメソッドを提供していません。したがって、このメソッドは私にはかなり厄介なようです。

ここでint.MaxValueを渡して問題を忘れたくなりますが、これについて何かがうまくいきません。

代わりに電話できることを知っています

byte[] value = (byte[])dataReader["columnName"];

..そしてこれは内部で長さの問題を完全に処理しているようです。ただし、私はSqlDataReader.GetXXXX()メソッドを中心に構築された一連の複雑なコード生成テンプレートを使用しています。したがって、私はGetBytesの使用に縛られており、その適切な使用法を理解する必要があります。

24
Martyn

varbinary(max)を扱う場合、2つのシナリオがあります。

  • データの長さは中程度です
  • データの長さが大きい

GetBytes()は、_CommandBehaviour.SequentialAccess_を使用してデータをストリーミングしていることを確認する場合のsecondシナリオを対象としています。 、バッファリングではありません。特に、この使用法では、通常、(たとえば)ストリームまたはループで書き込みます。例えば:

_// moderately sized buffer; 8040 is a SQL Server page, note
byte[] buffer = new byte[8040]; 
long offset = 0;
int read;
while((read = reader.GetBytes(col, offset, buffer, 0, buffer.Length)) > 0) {
    offset += read;
    destination.Write(buffer, 0, read); // Push downstream
}
_

しかしながら!適度なサイズのデータ​​を使用している場合、元のコードは次のとおりです。

_byte[] data = (byte[])reader[col];
_

大丈夫です!!。このアプローチには何の問題もありません。実際、_Get*_ APIが壊れている場合があります-GetChar()は注目すべき例です(ヒント:動作しません)。

_Get*_を使用する既存のコードがあるかどうかは関係ありません-この場合、キャストアプローチは完全に適切です。

38
Marc Gravell

あなたはおそらくこれを行うことができます。 MSDNで見つかりました。おそらくそれはあなたの目的を果たすことができます

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

http://msdn.Microsoft.com/en-us/library/87z0hy49%28v=vs.71%29.aspx#Y132

またはこれ

int ndx = rdr.GetOrdinal("<ColumnName>");
            if(!rdr.IsDBNull(ndx))
           {
            long size = rdr.GetBytes(ndx, 0, null, 0, 0);  //get the length of data
            byte[] values = new byte[size];

            int bufferSize = 1024;
            long bytesRead = 0;
            int curPos = 0;

            while (bytesRead < size)
            {
                bytesRead += rdr.GetBytes(ndx, curPos, values, curPos, bufferSize);
                curPos += bufferSize;
            }
           }
2
Anand