使用SqlDataReader获取二进制数据

Ash*_*pta 35 c# ado.net

我有一个名为Blob(Id(int),Data(Image))的表.我需要使用SqlDataReader来获取图像数据.请注意,我不想将Response.Binarywrite()数据发送到浏览器.我只需要将二进制数据作为byte []来使用相同的内部操作.我能想到的唯一方法是使用SqlDataReader获取id并再次使用SqlCommand.ExecuteScalar()将其作为给定id的byte [].我可以只使用SqlDataReader(SqlCommand.ExecuteReader)将该图像数据作为byte []吗?我错过了什么吗?

And*_*ugh 64

你应该能够通过以下方式获得它:(byte[])reader["Data"].

另请注意,image数据类型已弃用,将在SQL Server的未来版本中删除; 使用varbinary(max)来代替.

  • 我甚至没有在.NET 4.0中的`SqlDataReader`上看到`Items`集合. (3认同)

Jon*_*eet 18

是的,你可以使用SqlDataReader.GetBytes.您可能希望null在第一次调用中传入缓冲区,找出有多少数据,然后使用适当大小的缓冲区再次调用它.

可能只能使用索引器并将结果转换为字节数组 - 我不确定.值得一试 :)

  • @ydobonmai:当您已经拥有正确大小的缓冲区时,为什么还要使用不同的缓冲区大小呢?你应该使用 `bytesRead` 而不是 `curPos`;您目前总是假设它读取了完整的缓冲区量。 (2认同)

Axa*_*dax 10

在.NET Framework 4.5中,您可以使用GetStream方法将二进制数据作为Stream访问.


Ash*_*pta 7

来自MSDN.不知道为什么我以前找不到.

    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.
      if(retval > 0) // if file size can divide to buffer size
          bw.Write(outbyte, 0, (int)retval); //original MSDN source had retval-1, a bug
      bw.Flush();

      // Close the output file.
      bw.Close();
      fs.Close();
    }

    // Close the reader and the connection.
    myReader.Close();
    pubsConn.Close();
Run Code Online (Sandbox Code Playgroud)

  • 关于这一点的一个注意事项:如果你没有在ExecuteReader调用上设置CommandBehavior.SequentialAccess(例如从数据层的另一部分获取读取器),它将对你的内存做一些可怕的事情(为每个创建一个blob大小的字节数组)调用GetBytes()); 此解决方案应仅与CommandBehavior.SequentialAccess一起使用,如此处所示. (5认同)
  • 任何人都可以就如何决定缓冲区大小提出意见吗?该示例使用100,但为什么不使用10,为什么不使用10,000?需要考虑的因素是什么? (2认同)