2012-07-17 12 views
6

Mam problem z odczytaniem blobów z bazy danych MySQL. Zrobiłem to, aby pomyślnie wstawić do bazy danych, ale nie mogę tego odczytać. Wiem, że niektórzy z was mogą pomyśleć: "dlaczego używa bazy danych do przechowywania obiektów typu blob dla obrazów, a nie tylko ścieżek plików/nazw plików", ale chcę mieć elastyczność, a wiele z tych obrazów będzie przechowywanych na serwer, a nie lokalnie, optymalizuje to wydajność, a także pozwala przenosić obrazy do lokalnych, jeśli to konieczne. Poszedłem za (krótkim) samouczkiem i napisałem następującą metodę otrzymywania bloba;czytanie obrazu BLOB z bazy danych MySQL

public void getBlob(string query, string fileOut) 
    { 
     if (this.OpenConnection() == true) 
     { 
      MySqlCommand cmd = new MySqlCommand(query, mConnection); 

      //the index number to write bytes to 
      long CurrentIndex = 0; 

      //the number of bytes to store in the array 
      int BufferSize = 100; 

      //The Number of bytes returned from GetBytes() method 
      long BytesReturned; 

      //A byte array to hold the buffer 
      byte[] Blob = new byte[BufferSize]; 


      //We set the CommandBehavior to SequentialAccess 
      //so we can use the SqlDataReader.GerBytes() method. 

      MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess); 

      while (reader.Read()) 
      { 
       FileStream fs = new FileStream(DeviceManager.picPath + "\\" + reader["siteBlobFileName"].ToString(), FileMode.OpenOrCreate, FileAccess.Write); 
       BinaryWriter writer = new BinaryWriter(fs); 
       CurrentIndex = 0; 
       BytesReturned = reader.GetBytes(1, CurrentIndex, Blob, 0,BufferSize); 

       while (BytesReturned == BufferSize) 
       { 
        writer.Write(Blob); 
        writer.Flush(); 
        CurrentIndex += BufferSize; 
        BytesReturned = reader.GetBytes(1, CurrentIndex, Blob, 0, BufferSize); 
       } 

       writer.Write(Blob, 0, (int)BytesReturned); 
       writer.Flush(); 
       writer.Close(); 
       fs.Close(); 
      } 
      reader.Close(); 

      this.CloseConnection(); 
     } 
    } 

i jestem nazywając ją jak tak ..

mDBConnector.getBlob("SELECT siteMapPicture, siteBlobFilename FROM sites WHERE siteID = '" + DeviceManager.lastSite + "'", DeviceManager.picPath + "mappicsite" + DeviceManager.lastSite); 


PBSite.BackgroundImage = Image.FromFile(DeviceManager.picPath + "mappicsite" + DeviceManager.lastSite); 

Jednak to erroring na BytesReturned = reader.GetBytes (1, CurrentIndex, Blob, 0, BufferSize); z błędem "GetBytes można wywoływać tylko w kolumnach binarnych lub GUID". Zakładam, że ma to związek z moim typem pola w mojej bazie danych, ale zmiana kolumny na typ binarny oznacza, że ​​muszę przechowywać ją jako typ blob, ale chcę pozostawić nazwę pliku tak jak zwykły ciąg znaków. Czy jest coś, czego mi brakuje? lub inny sposób robienia tego?

edit1: Myślę, że pierwszym parametrem dla bajtów jest zrobić z kolumną w czytniku, ustawienie tego na 0 daje błąd "Nieprawidłowa próba odczytu poprzedniej kolumny przy użyciu SequentialAccess", źle się przyjrzyj.

edit2: Usunięcie dostępu sekwencyjnego daje mi plik o rozmiarze 13 bajtów (który może być tylko pierwszym wierszem, dlatego sekwencyjny dostęp odczytuje wszystkie wiersze?), Więc może czytam kolumny w niewłaściwej kolejności ..

Edytować 3: Wierzę, że powodem tego błędu było ze względu na sposób wprowadzania do bazy danych. po zmianie tej metody, moja saveBlob wygląda teraz tak:

public void saveBlob(string filePath, string fileName, string siteID) 
    { 
     if (this.OpenConnection() == true) 
     { 

      //A stream of bytes that represnts the binary file 
      FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read); 

      //The reader reads the binary data from the file stream 
      BinaryReader reader = new BinaryReader(fs); 

      //Bytes from the binary reader stored in BlobValue array 
      byte[] BlobValue = reader.ReadBytes((int)fs.Length); 

      fs.Close(); 
      reader.Close(); 


      MySqlCommand cmd = new MySqlCommand(); 
      cmd.Connection = mConnection; 
      cmd.CommandType = CommandType.Text; 
      cmd.CommandText = "INSERT INTO x (y, z) VALUES (@BlobFile, @BlobFileName)"; 

      MySqlParameter BlobFileNameParam = new MySqlParameter("@BlobFileName", SqlDbType.NChar); 
      MySqlParameter BlobFileParam = new MySqlParameter("@BlobFile", SqlDbType.Binary); 
      cmd.Parameters.Add(BlobFileNameParam); 
      cmd.Parameters.Add(BlobFileParam); 
      BlobFileNameParam.Value = fileName; 
      BlobFileParam.Value = BlobValue; 



       cmd.ExecuteNonQuery(); 

      this.CloseConnection(); 
     } 
    } 

i już biegł przez debugger, a zarówno blobvalue i blobfileparam (@blobfile) mają w pełnym rozmiarze (około 150k), ale to erroring po wykonaniu zapytanie, podając następujący błąd;

"unable to cast object of type 'system.byte[]' to type 'system.iconvertible" 

Wziąłem spojrzeć na kod i próbował zmienić typy binarnych do zdjęcia, aby umożliwić większe pliki, ale daje ten sam błąd. Ktoś wie coś na temat tej nowej informacji?

edycja 4: naprawiono wszystko. Zauważyłem, że w moim kodu używałem:

("@BlobFile", SqlDbType.Binary); 

Zmieniono je do typów „MySqlDbType” (Derp) i to pozwoliło mi wybrać typy blob. Rzeczy w końcu działają zgodnie z przeznaczeniem:)

+1

Nie jestem ekspertem w C#, ale jesteś wybierając 2 kolumny - '' i 'siteMapPicture siteBlobFilename' - oba są plamy lub jeden varchar/char/text? –

+0

siteMapPicture jest obiektem typu BLOB, nazwa obiektu siteBlob to varchar –

+0

Nie jest to programista w języku C#, ale czy pole blob nie powinno być kolumną # 0, podczas gdy próbujesz pobrać bajty z kolumny nr 1, która mogłaby być polem ścieżki? –

Odpowiedz

3

Czy próbowałeś najpierw uprościć? Zamiast odczytywania 100 bajtów BLOB na raz, spróbuj uprościć swój kod tak, aby po prostu odczytał wszystkie bajty do pliku. W ten sposób można łatwo wykluczyć problemy z warstwą danych.

Poniższa dokumentacja sugeruje także zapisać swój rozmiar pliku w innej kolumnie: http://dev.mysql.com/doc/refman/5.5/en/connector-net-programming-blob.html

Powiązane problemy