2012-07-17 21 views
6

Bir MySQL veritabanından bir blob okuyarak sorun yaşıyorum. Veritabanına başarılı bir şekilde eklemek için aldım, ancak geri okumak için görünmüyor olabilir. Bazılarınızın "neden sadece dosya yollarını/dosya adlarını değil, resimler için lekeleri saklamak için bir veritabanı kullandığını" düşündüğünü biliyorum, ancak esneklik sağlamak istiyorum ve bu görüntülerin bir çoğu Sunucu yerel olarak değil, bu da verimliliği optimize ediyor ve gerektiğinde görüntüleri yerel olarak taşımamı sağlıyor. Bir (kısa) dersi takip ettim ve bir blob almak için şu yöntemi yazdım;MySQL veritabanından BLOB görüntüsü okuma

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

ve şöyle ben bunu diyorum ..

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

o BytesReturned = reader.GetBytes üzerinde erroring oluyor Ancak (1, CurrentIndex, Blob, 0, BufferSize); "GetBytes yalnızca ikili veya guid sütunlarına çağrılabilir" hatasıyla. Bunun benim veritabanımdaki alanımla ilgili olduğunu farz ediyorum, ama ikilinin türünü değiştirmek için sütunları değiştirdiğimde, bunu bir blob türü olarak saklamak zorundayım, ancak dosya adını normal bir dizge olarak bırakmak istiyorum. Kaybettiğim bir şey mi var? ya da bunu yapmanın başka bir yolu?

edit1: bence bytesreturned için ilk parametre okuyucunun sütunla ilgili olduğunu, bunu 0'a ayarlayarak "SequentialAccess'i kullanarak önceki bir sütunu okumaya yönelik başarısız giriş" hatası veriyorsa, bu konuya bakın.

edit2: Sıralı erişimin kaldırılması bana 13 byte boyutunda bir dosya verir (bu sadece ilk satır olabilir, bu yüzden sıralı erişim tüm satırları okuyabilir mi?) Bu yüzden yanlış sırada sütunları okuyorum.

3: Bu hatanın nedeninin veritabanına girdiğimden kaynaklandığına inanıyorum. i ayıklayıcıya aktı ettik

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

ve blobvalue ve blobfileparam (@blobfile) hem (150k civarında) tam büyüklüğe sahip, ancak yürütme üzerine erroring ediyor: Bu yöntemi değiştirildi sahip, benim saveBlob şimdi gibi pek görünüyor aşağıdaki hatayı veren sorgu;

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

i koduna inceledik ve büyük dosyaları izin vermek, görüntüye ikili türlerini değiştirmek için çalıştı, ama aynı hata veriyor ettik. Bu yeni bilgiler hakkında bir şey bilen var mı?

4: her şeyi düzeltildi. Benim kodunda i kullanıyordum fark:

("@BlobFile", SqlDbType.Binary); 

türleri "MySqlDbType" bu Değişti (derp) ve bana blob'un türlerini seçmek için izin verdi. İşler sonunda amaçlandığı gibi çalışıyor:)

+1

hiçbir C# uzman değilim, ama sen 2 sütun seçiyoruz - 'siteMapPicture' ve 'siteBlobFilename' - Her iki lekeler veya biridir varchar/Char/metin? –

+0

siteMapPicture bir BLOB'tur, siteBlobFilename bir varchardır –

+0

Bir # # geliştiriciniz yok, ama blob alanınız # 0 sütununda olmazken, # 1 sütununda getbyte almaya çalışıyorsunuz, bu da yol alanı olur mu? –

cevap

3

İlk önce basitleştirmeyi denediniz mi? BLOB 100 byte'ları bir seferde okumak yerine, kodunuzu bir dosyaya bütün baytları okumak için basitleştirmeyi deneyin. Bu sayede veri katmanı sorunlarını kolayca belirtebilirsiniz.

aşağıdaki belgeler de başka sütun olarak dosya boyutunu depolamak öneriyor: http://dev.mysql.com/doc/refman/5.5/en/connector-net-programming-blob.html

İlgili konular