Makale Özeti

Hiç veritabanyna resim kayıt etmeye çalıştınız mı? Ben denedim, ve bakın nelerle karşılaştım.

Makale

ImageDataType

SQL SERVERDA İKİLİ FORMATTA
VERİ KAYIT ETME VE VERİ ELDE ETME

Hiç veritabanına resim kayıt etmeye çalıştınız mı? Ben denedim, ve bakın nelerle karşılaştım.

SQL Serverdaki image veritipi ikili olarak en fazla 8000 ikili (byte) saklayabiliyor. 8000 ikili (byte) gibi yüksek miktarda veri saklayabilmesi sayesinde, veritabanında image veritipi olan bir alanda dosya saklayabiliriz. Bu, resim dosyalarının yanında, herhangi bir dosyayı (*.zip,...) da veritabanında tutabileceğimiz anlamına geliyor.

Resim kayıt etme ile ilgili bir örnek uygulama yapalım.

Bu uygulamayı yapabilmek için SQL Serverda Query Analyzer kullanabilmekle beraber, ADO.NET bilgisine sahip olmanız gerekir.

Örnek Uygulama

Örneğimizde, veritabanına istediğimiz resmi kayıt edeceğiz.. Daha sonra, kayıt ettiğimiz bu resmi, resim kutusunda görüntüleyeceğiz.

İlk önce veritabanında kullanacağımız tabloları ve sorgular için saklı yordamları oluşturalım.

Veritabanı Tablosunun Oluşturulması

SQL Serverda Resim Veritabanı isminde bir tane veritabanı oluşturalım. Query Analyzerda aşağıdaki T-SQL kodunu kullarak veritabanında ResimTablosu adında bir tablo oluşturalım. Tabloda kayıt edeceğimiz resmin ismini tutan ResimAd alanını ve resmimizi ikili formatta tutacak olan image veritipindeki Resim alanını tanımlayalım.

USE [Resim Veritabanı]
GO

CREATE TABLE ResimTablosu
(
ResimAd char (10),
Resim image NULL
)
GO

Veritabanında Gerekli Saklı Yordamların Oluşturulması

Resmi kayıt etmek ve kayıt edilen resmi elde etmek için saklı yordamlar kullanarak sorgu yapabiliriz.

Resmi kayıt etmek için oluşturacağımız saklı yordam, resmin ismini ve resmin ikili formatını dışarıdan parametre alan bir saklı yordamdır. Query Analyzerda yazacağımız kod aşağıdaki gibidir.

USE [Resim Veritabanı]
GO

CREATE PROCEDURE ResimKaydet
@ResimAd AS VARCHAR(255),
@Resim AS IMAGE
AS
INSERT INTO
ResimTablosu(ResimAd,Resim)
VALUES ( @ResimAd, @Resim )

GO

Veritabanından, kayıtlı olan herhangi bir resmi ismi ile çağırabilmek için gerekli saklı yordam, dışarıdan resmin ismini parametre olarak almaktadır. Query Analyzerda yazacağımız kod aşağıdaki gibidir.

USE [Resim Veritabanı]
GO

CREATE PROCEDURE ResimGetir
@ResimAd AS VARCHAR(255)
AS
SELECT
Resim
FROM ResimTablosu
WHERE ResimAd = @ResimAd

GO

Böylece veritanını kullanacağımız tabloyu, ve sorgular için kullanacağımız saklı yordamlarımızı oluşturmuş olduk.

Projenin Oluşturulması

Formumuzu aşağıdaki gibi tasarlayalım:


1.Şekil: Form Tasarımı

Sabit diskimizin herhangi bir yerinde olan resmi eklemek için Resim Ekle komut düğmesini, veritabanındaki hangi resmi görüntületmek istediğimizi bildirmek için bir metin kutusunu, resmi görüntülemek için Resim Görüntüle komut düğmesini ve resmi görüntületeceğimiz bir resim kutusunu forma yerleştirelim. Bir de herhangi bir hata olduğunda hatayı ve/veya projemizin hangi işlemi gerçekleştirdiğini anlamak için bir etiket koyalım. Formdaki kontrollerin isimlerini aşağıdaki gibi değiştirelim.

Button1 : btnResimEkle
Button2 : btnResimGoruntule
TextBox1 : txtResimIsmi
Label1 : lblDurum
PictureBox1 : pb
1.Tablo: Kontrol İsimleri

SQL veritabanına bağlanacağımız için System.SqlClient isim uzayını, ve dosya işlemleri yapacağımız için System.IO isim uzayını projemize ekliyoruz.

Imports System.Data.SqlClient
Imports System.IO

Kullanacağımız değişkenleri projemizin en başında tanımlıyoruz. Ne için kullanacağımız yanlarında açıklama olarak yazmaktadır.

    Dim strConn As String bağlantı cümleciği için
    Dim cnnSql As SqlConnection bağlantı kurmak için
    Dim cmdSql As SqlCommand sorgulama yapmak için
    Dim param As SqlParameter sorguya parametre eklemek için

Bağlantıyı sağlamak için Baglan isimli bir fonksiyon tanımlıyoruz.

   Public Sub Baglan()
        Veritabani bağlantısı için ayarlamalar yapıyoruz.
         Try
            hangi sunucuya (kendi makinem),hangi veritabanına (Resim Veritabani) ve hangi kullanıcıyla(sa) baglanacağımızı bağlanti cümleciğiyle belirtiyoruz.
            strConn = ("server=(local); database=Resim Veritabani;user id=sa")
            olusturduğumuz SqlConnection nesnesine bağlantı cümleciğini atıyoruz.
            cnnSql = New SqlConnection(strConn)
            bağlantıyı açıyoruz.
            cnnSql.Open()
            lblDurum.Text = "Bağlanti sağlandı"
        Catch uyari As Exception
            lblDurum.Text = "Bağlanti Hatası: " & uyari.Message
        End Try
    End Sub

Veritabanına resim kayıt etmek için kullanacağımız komut düğmesinin arkasındaki kodlar aşağıdaki gibidir. Açıklamalar kod aralarında yapılmaktadır.

    Private Sub btnResimEkle_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnResimEkle.Click
        açmak istediğimiz dosyanın ismini tutacak olan değişkeni tanımlıyoruz.
        Dim dosya As String
        dosya seçmek için OpenFileDiyalog kutusu kullanacağız. Yeni bir tane türetiyoruz.
        Dim dlgAc As New OpenFileDialog
        Try
            ne tür dosyalar açmak istiyorsak ona göre filtreleme yapiyoruz.
            dlgAc.Filter = "Resim Dosyalari (*.jpg)|*.jpg|Bütün Dosyalar(*.*)|*.*"
            iletişim kutusu çıkması için OpenFileDialog nesnesinin ShowDialog komutunu kullanıyoruz.
            dlgAc.ShowDialog()

Açılan iletişim penceresinden bir resim seçelim.


2.Şekil: jpg formatında bir dosya seçme.

Seçtiğimiz dosya ismini string türündeki dosya değişkeninde tutuyoruz.

dosya = dlgAc.FileName

Dosya ismini elde ettiğimiz resmi veritabanına kayıt etmek için ResmiVeritabaninaKaydet(Dosya İsmi) alt yordamını çağırıyoruz. Dosya ismini alt yordama parametre olarak gönderiyoruz.

ResmiVeritabaninaKaydet(dosya)
lblDurum.Text = dosya & " veritabanina kayıt oldu."

Hata yakalamak için Catch bloğunu kullanıyoruz.

         Catch uyari As Exception
            lblDurum.Text = "dosya açma işleminde hata oldu"
         End Try
    End Sub

Veritabanına kayıt etmek için kullandığımız ResmiVeritabaninaKaydet(DosyaIsmi) alt yordamı aşağıdaki gibidir.

    Public Sub ResmiVeritabaninaKaydet(ByVal DosyaIsmi As String)
        Baglan fonksiyonu ile veritabanına bağlantı sağlıyoruz.
        Baglan()

Veri tabanında oluşturduğumuz ResimKaydet isimli saklı yordamı burada SqlCommand nesnemizin komut katarına atıyoruz.

        Try
            cmdSql = New SqlCommand("ResimKaydet", cnnSql)

Seçtiğimiz resim için bir akım tanımlıyoruz.

             Dim ResimAkimi As New FileStream(DosyaIsmi, FileMode.Open)

Veritabanında image veri tipi ikili (byte) olarak tutulduğu için, resmin bilgisini ikili (byte) dizisi olarak tutacağımız değişkeni tanımlıyoruz.

            Dim uzunluk = ResimAkimi.Length

Dizinin boyutunu akımın boyutu olarak belirliyoruz.

            Dim ResimBilgisi(uzunluk) As Byte

Resim bilgisini okuyoruz ve akımımızı kapatıyoruz.

            ne okuyacağımız=resimBilgisi, okumaya nerden baslayacağımız=0 (ilk eleman), nereye kadar okuyacağımız=uzunluk(Resim akımının uzunluğu kadar) okuma işleminde belirtiyoruz.
            ResimAkimi.Read(ResimBilgisi, 0, uzunluk)
            ResimAkimi.Close()

Komut nesnemizin ayarlarını yapıyoruz.

            kullanacağımız komut nesnesinin komut türünün saklı yordam olduğunu belirtiyoruz.
            cmdSql.CommandType = CommandType.StoredProcedure
            saklı yordamın alacağı parametreleri gönderiyoruz.
            param = New SqlParameter("@ResimAd", SqlDbType.VarChar, 255)
            göndereceğimiz parametrenin değerini bizim seçmiş olduğumuz dosyanın ismini temsil eden DosyaIsmi değiskeni  olarak atıyoruz.
            param.Value = Path.GetFileName(DosyaIsmi)
            parametreyi Command nesnesinin parametrelerine ekliyoruz.
            cmdSql.Parameters.Add(param)
            resmin bilgisi temsil eden ve image veri türünden olan bir parametre oluşturuyoruz.
            param = New SqlParameter("@Resim", SqlDbType.Image)
            değerini ikili dizisi olan ResimBilgisi olarak atıyoruz.
            param.Value = ResimBilgisi
            parametreyi Command nesnesinin parametrelerine ekliyoruz.
            cmdSql.Parameters.Add(param)

Komutu çalıştırıyoruz.

            cmdSql.ExecuteNonQuery()

Bağlantımızı kapatıyoruz.

            cnnSql.Close()
            lblDurum.Text = "Resim Kayit Edildi"

Hata varsa yakalama işlemi gerçekleştiriyoruz..

        Catch uyari As Exception
            lblDurum.Text = "Resim Kayıt Edilemedi!!! Hatanın sebebi: " & uyari.Message
        End Try
     End Sub

Bu şekilde veritabanına gösterdiğimiz resmi ikili (binary) bir şekilde kayıt etmiş olduk.

Şimdi de, kayıt ettiğimiz resimleri resim kutusunda görüntüleyerek nasıl elde ettiğimize bakalım.

Resim Görüntüle komut düğmesinin arkasına aşağıdaki kodları yazalım.

    Private Sub btnResimGoruntule_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnResimGoruntule.Click
        Baglan fonksiyonu ile baglanti sağlıyoruz.
        Baglan()
        Try
            veritabanında kayıtlı olan ResimGetir saklı yordamını komut nesnemizin komut katarı olarak belirliyoruz.
            cmdSql = New SqlCommand("ResimGetir", cnnSql)
            veritabanına kayit ettiğimiz resmin ismini metin kutusuna girerek, o resmi veritabanından çekmek istediğimizi belirtiyoruz.
            Dim ResimIsmi As String
            ResimIsmi = txtResimIsmi.Text
            komut nesnesinin parametre ayarlarını yaparak, saklı yordama gerekli olan değişkenleri gönderiyoruz.
            cmdSql.CommandType = CommandType.StoredProcedure
            param = New SqlParameter("@ResimAd", SqlDbType.VarChar, 255)
            param.Value = ResimIsmi
            cmdSql.Parameters.Add(param)

Resim bilgisini tutacak ikili (byte) türünden bir dizi tanımlıyoruz . Komut nesnemizin ExecuteScalar fonksiyonunun dönderdiği değeri Byte() türünden diziye çevirerek ResimBilgisine atama yapıyoruz.

            Dim ResimBilgisi() As Byte
            ExecuteScalar : birinci kolonun birinci satırını dönderir.//
            ResimBilgisi = CType(cmdSql.ExecuteScalar, Byte())

Resim bilgisini içeren ikili diziyi kullanarak bir akım oluşturuyoruz.

            Dim ResimAkimi As MemoryStream
            ResimAkimi = New IO.MemoryStream(ResimBilgisi)

Resim kutusuna o bilgi sayesinde resim yükletebiliyoruz.

            pb.Image = Image.FromStream(ResimAkimi)
            lblDurum.Text = "Resim Görüntülendi"

Hata olup olmadığını kontrol amacıyla Try-Catch mekanizması kullanıyoruz.

         Catch uyari As Exception
            lblDurum.Text = uyari.Message
        End Try
    End Sub

Bu şekilde projemizi çalıştırdığımızda, veritabanında kayıt etmiş olduğumuz resmin ismini metin kutusuna yazdığımızda, resmi resim kutusunda görmüş olacağız.


3.Şekil : Kayıt ettiğimiz resmin görüntülenmesi.

Veri Tabanında Neler Oluyor?

Query Analyzerda aşağıdaki komutu yazalım :

USE [Resim Veritabanı]
GO
SELECT * FROM ResimTablosu

 


4.Şekil : Resmin ikili şekilde kayıt edilmesi.

Çıktı olarak, bizim projemizde kayıt ettiğimiz resmin ismini, ve image veritipindeki alanda da, onun ikili bir şekilde kayıt edilmiş halini görürüz.

Aslında veritabanında resim kayıt etmek, veritabanına ek yük getirmiş olacak. Peki niçin resimleri veritabanında kayıt etmemiz gerekir? Program geliştirirken, eğer resimle ilgili bir işlem yapmak gerekirse, resmin bilgisayarımızdaki adresi veritabanında tutarak, veritabanının yükü hafifletebiliriz.. Ancak ya resimlerim bulunduğu klasörü taşımamız gerekirse? İşte o zaman bütün resimlerin yolunu tek tek değiştirmek zorunda kalırız. Resimleri veritabanına, ikili bir şekilde saklayarak, olabilecek sorunlara karşı önceden önlem almış oluruz.

Öznur KARAKUŞOĞLU
SQLNedir?com