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:)
Nie jestem ekspertem w C#, ale jesteś wybierając 2 kolumny - '' i 'siteMapPicture siteBlobFilename' - oba są plamy lub jeden varchar/char/text? –
siteMapPicture jest obiektem typu BLOB, nazwa obiektu siteBlob to varchar –
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? –