C# - Kép tárolása, felhasználása MS SQL adatbázisból

forráskód letöltése
SQL adatbázis tábláiban történő képek tárolása és kiolvasása (vagyis a kép megjelenítése) némi többlet munkát igényel, mint mondjuk egy int típusú adat tárolása, kiolvasása.
Mellékelt példában annak járunk utána, hogy miként helyezhetünk egy tábla adott mezőjébe tetszőleges méretű képet, majd hogyan jeleníthetjük meg az így eltárolt képeket a Form-on.
A mellékelt példa használatához a következő lépések szükségesek: a Pictures.sql állományban lévő sql utasításokat futtassa le, hogy létrejöjjön a példához szükséges Pictures nevű adatbázis. Ezek után a Form1.cs forráskód 124. sorában módosítsa a connStr változó értékét, hogy a Pictures adatbázis elérhető legyen.
Kép tárolása a táblában
Adott egy 1.bmp nevű állomány. Ezt a képet szeretnénk eltárolni a Pictures adatbázis Table1 táblájának egy új sorába. Ehhez a következőt kell tennünk: olvassuk be ezt az állományt egy bájtokat tartalmazó tömbbe a FileStream osztály használatával.
    private void button1_Click(object sender, System.EventArgs e)
    {
      FileStream fs = new FileStream(Application.StartupPath+"\\1.bmp", FileMode.Open, FileAccess.Read);
      byte[] imageData = new Byte[fs.Length];
      fs.Read(imageData, 0, (int)fs.Length);
      fs.Close();      
      ...
Ezt követően meghívunk egy tárolt eljárást, melyet már létrehoztunk a Pictures adatbázisunkba InsertPicture névvel.
      SqlCommand c = new SqlCommand("InsertPicture", connection);
      c.CommandType = CommandType.StoredProcedure;
A tárolt eljárás két paramétert vár. Az elsőben megadhatunk szövegesen egy azonosítót, mely a képünket írja le. A második maga a kép lesz, mely egy Image típusú oszlopban kap helyet.
      c.Parameters.Add("@PictureIDValue", SqlDbType.VarChar, 50);
      c.Parameters.Add("@PictureValue", SqlDbType.Image);
Ezt követően megadjuk a két paraméter értékét. A kép esetén a már létrehozott bájtokat tároló tömböt kell átadni.
      c.Parameters["@PictureIDValue"].Value="Első kép";
      c.Parameters["@PictureValue"].Value=imageData;
Végül már csak futtatjuk a tárolt eljárást, mely egy egyszerű insert into parancsot hajt végre.
      c.ExecuteNonQuery();
      ...
Kép megjelenítése a táblából
Ha már van tárolt képünk, akkor ezt valószínűleg el is szeretnénk érni és meg is jelenítenénk. Ehhez futtatunk egy egyszerű select lekérdezést, majd az eredmény olvasását egy SqlDataRead osztályra bízzuk.
    private void button2_Click(object sender, System.EventArgs e)
    {
      ...
      SqlCommand c = new SqlCommand("select * from Table1", connection);
      SqlDataReader dr = c.ExecuteReader();
      dr.Read();
A szöveges oszlop elérése és adatának megjelenítése egyszerű:
      label1.Text = dr.GetString(0);
A kép eléréséhez szintén egy bájt tömbre lesz szükségünk első lépésben, csak hogy most nem tudjuk, hogy mekkora képet tároltunk el és ehhez mekkora bájt tömböt kellene létrehoznunk. Ezért először az SqlDataRead osztály GetBytes függvényét úgy futtatjuk, hogy nem adunk meg buffert, melyre a bájtokat másolhatná, így eredményül visszakapjuk, hogy hány bájtra van szükség a tömbben az adott kép tárolásához. Felhasználva ezt az értéket, most már létre tudjuk hozni a tömböt a megfelelő mérettel, majd egy ismételt GetBytes függvény hívással most már kiolvashatjuk a bájtokat, melyek a képet alkotják.
      long bytesize = dr.GetBytes(1, 0, null, 0, 0);
      byte[] imageData = new byte[bytesize];
      dr.GetBytes(1, 0, imageData, 0, (int)bytesize);
Most már csak a bájtokból kellene használható formátumú képet előállítanunk. Ehhez több műveletre is szükség lesz. Először is a bájt tömb tartalmát egy memória stream-en tároljuk.
      MemoryStream ms = new MemoryStream();
      ms.Write(imageData, 0, imageData.Length);
Ezt követően létrehozunk egy Bitmap osztályt, melynél a memória stream adatait használjuk fel. Így előáll az adattáblában tárolt kép Bitmap osztálybeli megfelelője.
      Bitmap bmp = new Bitmap(ms);             
Ha már adott a Bitmap osztályban a kép, akkor már bármit megtehetünk: menthetjük állományba, vagy akár meg is jeleníthetjük rögtön:
      Graphics g = Graphics.FromHwnd(Handle);
      g.DrawImage(bmp, 30, 150); 
    }