web-dev-qa-db-fra.com

Obtention de données binaires à l'aide de SqlDataReader

J'ai une table nommée Blob (Id (int), Data (Image)). J'ai besoin d'utiliser SqlDataReader pour obtenir ces données d'image. Notez que je ne veux pas Response.Binarywrite () les données du navigateur. J'ai juste besoin de ces données binaires en octet [] pour les utiliser pour certaines opérations internes. La seule façon dont je peux penser est d'obtenir id en utilisant SqlDataReader et d'utiliser à nouveau SqlCommand.ExecuteScalar () pour obtenir cela comme octet [] pour un id donné. Puis-je utiliser uniquement le SqlDataReader (SqlCommand.ExecuteReader) pour obtenir ces données d'image sous forme d'octet []? Suis-je en train de manquer quelque chose?

35
Ashish Gupta

Vous devriez pouvoir l'obtenir via: (byte[])reader["Data"].

Notez également que le type de données image est obsolète et sera supprimé dans une future version de SQL Server; utilisez plutôt varbinary(max).

63
Andy Edinborough

Oui, vous pouvez utiliser SqlDataReader.GetBytes . Vous souhaiterez probablement passer null pour le tampon lors du premier appel, pour connaître la quantité de données, puis l'appeler à nouveau avec un tampon de taille appropriée.

Vous pouvez simplement utiliser l'indexeur et transtyper le résultat dans un tableau d'octets - je ne suis pas sûr. Ça vaut le coup d'essayer :)

18
Jon Skeet

Dans .NET Framework 4.5, vous pouvez utiliser la méthode GetStream pour accéder aux données binaires en tant que Stream.

10
Axarydax

De MSDN . Je ne sais pas pourquoi je n'ai pas pu trouver ça avant.

    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();
7
Ashish Gupta

Utilisez cette fonction pour une lecture d'octets sûre et flexible:

    /// <summary>
    /// Reads all available bytes from reader
    /// </summary>
    /// <param name="reader"></param>
    /// <param name="ordinal"></param>
    /// <returns></returns>
    private byte[] GetBytes(SqliteDataReader reader, int ordinal)
    {
        byte[] result = null;

        if (!reader.IsDBNull(ordinal))
        {
            long size = reader.GetBytes(ordinal, 0, null, 0, 0); //get the length of data 
            result = new byte[size];
            int bufferSize = 1024;
            long bytesRead = 0;
            int curPos = 0;
            while (bytesRead < size)
            {
                bytesRead += reader.GetBytes(ordinal, curPos, result, curPos, bufferSize);
                curPos += bufferSize;
            }
        }

        return result;
    }
2
Anton Bakulev

Pas besoin d'utiliser le lecteur. Utilisez simplement un ensemble de données pour récupérer les valeurs de la base de données (en utilisant Proc stocké ou toute autre méthode) et tapez simplement le cast avec octet (code ci-dessous) et stockez-le dans un tableau d'octets. Votre travail est terminé.

byte[] productImage;
productImage = (byte[])ds.Tables[0].Rows[0]["Image"];
1
user1768031