Makale Özeti

Merhaba arkadaşlar bu makalemizde kendi veritabanı motorumuzu nasıl yazacağımızı anlatacağım. Aslında buna veritabanı motoru demek ne kadar doğrudur bilemiyorum ama çok işimize yarayacak ve her yerde kullanabileceğimiz bir dll olacağı kesin. Veritabanı motoru demişken kendi başına bağımsız çalışan bir sistem değil yani bu yazacağımız dll sql kullanacak ve ben bu makalem de Access için yazacağımız basit ama çok kullanışlı komutlardan bahsedeceğim. Tabi siz daha da gelişmiş bir sistem yazabilirsiniz.

Makale

Merhaba arkadaşlar bu makalemizde kendi veritabanı motorumuzu nasıl yazacağımızı anlatacağım. Aslında buna veritabanı motoru demek ne kadar doğrudur bilemiyorum ama çok işimize yarayacak ve her yerde kullanabileceğimiz bir dll olacağı kesin. Veritabanı motoru demişken kendi başına bağımsız çalışan bir sistem değil yani bu yazacağımız dll sql kullanacak ve ben bu makalem de Access için yazacağımız basit ama çok kullanışlı komutlardan bahsedeceğim. Tabi siz daha da gelişmiş bir sistem yazabilirsiniz.

       

        Öncelikle C# ta bir dll projesi açalım. Bunun için c# ı açtıktan sonra yeni proje seçeniğinden class library templatini seçelim.

 

Sonra ismine Veritabani yazarak kaydedelim. Proje açıldığında ilk önce sınıf yapımızda bazı değşiklikler yapalım. Ben access için anlatacağım. Zaten sql  server veya mysql için kodlarda fazla bir değişiklik olmayacak mesela Access te select sorgusunu çalıştırmak için ihtiyaç duyduğumuz nesne OledbDataAdapter nesnesidir mysql de ise MysqlDataAdapter dir. İki nesneninde kullanım şekli aynıdır. Class ismini Class1.cs değilde Access.cs olarak değiştirelim. Sonra using isim uzaylarının bulunduğu alana bazı referanslar ekleyelim:

 

using System.Data;

using System.Data.Oledb;

using System.Windows.Forms;

 

Bunları yazdıktan sonra dll projemize windows form nesnelerini kullanabilmek için System.Windows.Forms.dll dosyasını projemizde kullacağımızı belirtmemiz lazım. Bunun için menüden Project -> Add reference… komutunu seçelim. Karşımıza çıkan pencereden .Net sekmesine gelelim. Ordan System.Windows.Forms nesnesini seçip tamam butonuna tıklayalım. Böylece Form nesnelerinide dll projemizde kullanabilmiş olacağız. Fakat class yapımızda yapmamız gereken bir şey daha var. Public class Access yazan yeri public static class Access olarak değiştirelim ki projelerimizde bunun yavru değişkenini oluşturmadan direk olarak kullanabilelim. Bunu da yaptıktan sonra class yapımız artık hazırdır. Şimdi sql komutlarını kullanabilmek için yazacağımız komutlara bakalım öncelikle alıştırma olması açısından basit bir test komutu yazacağız bize bağlantının olup olmadığını söyleyen bir komut olacak ondan sonra birkaç komut daha yazacağız sonra da bu dll dosyasını yeni projemizde nasıl kullanacağımızı anlatacağım. Başlıyoruz:

 

//Öncelikle değişkenlerimizi tanımlayalım. Public static class Access in altına.

        public static OleDbConnection c = new OleDbConnection();

        public static OleDbCommand com = new OleDbCommand();

        public static OleDbDataAdapter da;

        public static OleDbDataReader dr;

Bu değişkenleri de static olarak tanımlayalım ki bunlarada doğrudan erişebilelim. Sonra da ilk komutumuzu yazalım:

 

public static void Test()

        {

            try

            {

                c.Open();   //Bağlantıyı aç.

                c.Close();  //Bağlantıyı kapat.

                MessageBox.Show("Test başarılı", "Bağlantı Testi", MessageBoxButtons.OK, MessageBoxIcon.Information);

            }

            catch

            {

                MessageBox.Show("Test başarısız", "Bağlantı Testi", MessageBoxButtons.OK, MessageBoxIcon.Stop);

            }

        }

 

Bu projemizde yazacağımız tüm komutlar ve değişkenler static olmalı yoksa bunlara doğrudan erişemeyiz. Bu komutta c oledbconnection nesnesi artık içinde hangi veritabanına bağlanacaksa onu aç ve kapat eğer açma sırasında hata oluşmassa demek ki bağlantı sağlandı o zaman test başarılı mesajını ver eğer hata oluşursa catch bloğuna düşecek demek ki bağlantıda sorun var o zaman ise test başarısız mesajını görüntüle. Gördüğünüz gibi basit bir komut. Şimdi select sorgusunu kullanabilmek için bir komut daha yazalım.

 

 

 

public static bool Listele(string select, DataGridView dtg)

        {

            DataTable dt = new DataTable();

            try

            {

                dt.Clear();

                da = new OleDbDataAdapter(select, c);

                da.Fill(dt);

                dtg.DataSource = dt;

                return true;

            }

            catch

            {

 

                return false;

            }

        }

 

Bu komutun iki parametresi var ilk parametre select sorgusu için gereken string değişken, ikincisi ise bu select sorgusunun çalışacağı sonuçların görüntüleneceği datagridview nesnesi. Burda fark ettiyseniz Datatable nesnesi Listele metodunun içinde tanımlı bunun nedeni eğer global olarak tanımlanmış olsaydı diğer sorgudaki tablolarla karışacaktı yani sıkıntı çıkacaktı. Ben bunu denedim ve bazı istenmeyen durumlar oluştu ben de bu nesneyi zaten bu metod için kullandığımız için bunun içinde tanımlamanın daha doğru bir yaklaşım olduna karar verdim. Geriye kalan kodlar ise zaten bildiğiniz kodlar öncelikle dt değişkeni temizleniyor gerçi yeni tanımlanmış her defasında yeniden oluşturuluyor ama biz sıkıntı çıkmasın diye temizlemişiz. Sonra select sorgusu çalıştırılıyor. Sonra da verilen datagridde görüntüleniyor. Dtg.DataSource = dt; komutuyla. Dtg değeri bizim verdiğimiz datagrid oluyor bildiğiniz gibi. Kodlar try bloğu içinde eğer kodlar doğru çalışırsa hata olmazsa geriye dönen değer true oluyor. Hata oluşursa geriye dönen değer false oluyor. Bu metodun geriye değer döndürmesi için bir türü olmalı yani eğer void olursa geriye değer döndürmez. Geriye dönen değer true ya da false ise bu metodun türü bool olmalı. Şimdi de select hariç diğer sorguları çalıştırmak için gereken komutu yazalım. Bu komutta create, alter, drop, delete, insert, update vb. gibi bildiğiniz standart sql komutlarının çalışacağı komut olacak.

public static bool Sorgu_Çalıştır( string sql_komut)

        {

            try

            {

            c.Close();

            c.Open();

            com.Connection = c;

            com.CommandText = sql_komut;

            com.CommandType = CommandType.Text;

            com.ExecuteNonQuery();

            c.Close();

            return true;

            }

            catch

            {

                return false;

            }

}

Bu metod da geriye bool türünde değer döndürüyor ve tek parametresi var. Bu komutlarda zaten bildiğiniz kullandığınız komutlar. O yüzden burda fazla ayrıntıya girmiyorum. Şimdi de biraz daha alışılmışın dışında komutlar yazalım. Bu yazdığımız üç komut herkesin bildiği komutlardı gerçi şimdi yazacağımız komutunda diğerlerinden pek bir farkı yok ama kullanışı biraz farklı desem olur sanırım. Şimdi ki komutumuz Veri_Çek komutu bu komut şu işi yapacak örnek veriyorum urunler tablosundan 3.satırdaki 5.sütundaki bilgiyi bize verecek. Bu nasıl olacak işte bu şekilde:

 

public static string Veri_Çek( string tablo,  int satır,  int sutun)

        {

            string veri = "";

            int i = 0;

            try

            {

                c.Close();

                c.Open();

                com.CommandType = CommandType.TableDirect;

                com.CommandText = tablo;

                com.Connection = c;

                dr = com.ExecuteReader();

                while (dr.Read() == true)

                {

                    if (satır == i)

                    {

                        veri = dr[sutun].ToString();

                        break;

                    }

                    i++;

                }

                return veri;

            }

            catch (Exception ex)

            {

                return ex.Message.ToString();

            }

        }

 

Öncelikle metod bize veritabanından bir bilgi vereceği için geriye dönen değer string türünde olmalı. Sonra bu bilginin hangi tablodan olduğunu ve adresini satır sütun olarak yazmalıyız bunun içinde metod 3 parametreli oluyor. Bize vereceği bilgi string olduğu için bunu bir değişkene atması daha dorğu olur o değişken de string olarak tanımlanan veri değişkeni. Satırları sayabilmesi içinde bir integer değişken lazım o değişken de i ismiyle tanımlanmış. Sonra try içinde bağlantının açık olma ihtimaline karşı kapatılıyor. Eğer zaten kapalıysa bir sıkıntı olmaz. Sonra açılıyor. While döngüsüne kadar olan kısım tanıdıktır. Bu dögü içinde dr değişkeni okuma işlemini yapar. Bütün kayıtları okur. Bir değer almak istediğimizde dr[] köşeli parantez içinde o alanın adını ya da numarasını yazarız ben numarasını kullandım. Yani dr[0].ToString() dediğimizde o satırın 0. sütunda bulunan verisini bize verir. Verilen satır numarası satir değişkeninde saklanır. Döngü içinde i değişkeni i++; komutuyla sürekli bir artırılır. Eğer satir değişkeni ile i değişkeni eşitlenirse verilen satır numarası budur der ve if yapısının altına iner. İşte burda veri değişkenine belirtilen sütundaki bilgi atılır ve return komutuyla metodun çağırıldığı yere geri gönderilir.

       Arkadaşlar şimdi de bir başka komut olan oku komutumuzu yazalım.

 

   public static List<string> Oku( string tablo,  int sutun_no)
        {
            List<string> kayıtlar = new List<string>();
            kayıtlar.Clear();
            c.Close();
            try
            {
                c.Open();
                com.CommandType = CommandType.TableDirect;
                com.CommandText = tablo;
                com.Connection = c;
                dr = com.ExecuteReader();
                while (dr.Read()==true)
                {
                    kayıtlar.Add(dr[sutun_no].ToString());
                }
                return kayıtlar;
            }
            catch
            {
            return new List<string>();
            }
            
        }


  Arkdaşlar burda verilen tablodaki verilen satırdaki kayıtları bir list of string değişkeninde saklar. Yani biz bu komutu kullanarak kayıt sayısı öğrenebiliriz. Bu komut içinde tanımlı kayıtlar isimli list<string> değişkenine bizim verdiğimiz alandaki kayıtları .Add metoduyla ekler. Biz de bu komutu kullanarak kayıt sayısını ya da o alandaki istediğimiz satırdaki bilgiyi alabilir ya da o alanda arama yapabiliriz. Mesela Oku("kullanici", 0).Count yazdığımızda 0. alandaki kullanici tablosundaki kayıt sayısını elde edebiliriz. 0. alanın boş olup olmaması önemli değil eğer 0.alanda bilgi yok ama 1. alanda bilgi varsa ve 3 kayıtsa bize bu 3 olarak geri döner. Bu komutun kullanımını zaten birazdan göreceğiz.

Şöyle bir kurgu yapabiliriz. Arkadaşlarımızın bilgilerinin tutulduğu bir veritabanı hazırlayalım ve bu veritabanı üzerinde sql komutlarıyla ve tabiki de kendi yazdığımız veritabanı motorunu test edelim.

 

        Bunun için yeni bir proje açalım. Windows Fomrs Application uygulaması şeklinde olsun. Sonra projemizin debug klasörüne yeni bir access dosyası oluşturalım. İçine kisiler isminde yeni bir tablo açalım ve şu alanlara sahip olsun:

resim1

 

Sonra form tasarımımızı yapalım:

 

Daha sonra arkadaşlar projemize daha önce yazdığımız dll dosyasını reference olarak eklememiz lazım. Bunun için şöyle yapın Menüden Project -> Add reference komutunu tıklayın. Karşınıza çıkan pencereden browse sekmesine gelin burdan daha önce yazdığımız dll projesinin klasörüne girerek bin klasöründeki dll dosyasını seçip tamam butonuna tıklayın.

resim3

Artık yeni projemizde kendi veritabanı motorumuzuda kullanabileceğiz. Şimdi arkdaşlar kodları yazmaya geçelim. Forma çift tıklayarak form_load olayını açın buraya bir şey yazmadan önce using tanımlamarının olduğu alan gelin ve oraya dll projemizi kullanacağımızı belirtelim:

 

using vt=Veritabani.Access;


Sonra tekrar form load olayına gelin ve şu kodları yazın:

(Bunları yazmdan önce vt.Test(); metodunu çağırarak bağlantı sınaması yapabilirsiniz J)

            vt.c.ConnectionString = "provider=Microsoft.jet.oledb.4.0; data source=veri.mdb"; //Bağlantı cümlemiz.

            vt.Listele("Select * from kisiler", dataGridView1); //Listele komutumuz kisiler tablosundaki tüm kayıtları listeliyor dataGridView1 nesnemizde.

 

Arkdaşlar burda bağlantı cümlemizi ve select sorgusunu çalıştırdık. c değişkeni oledbconnection nesesiydi hatırlarsanız ve veritabanı motorumuzda bir değişkene veya bir komuta erişmek istiyorsak using tanımlamsında yaptığımız isimle vt. şeklinde yazarak kullanıyoruz.

 

        Arkadaşlar şimdi de kaydet butonuna insert komutunu yazalım:

 

vt.Sorgu_Çalıştır("insert into kisiler(adi,mail,dil, dogum_tarihi) values('"+ textBox1.Text +"', '"+ textBox2.Text +"', '"+ textBox3.Text +"', '"+ textBox4.Text +"')");

 

Bu kaydetme komutumuz kaydet butonuna tıkladığımızda çalışacak. Fakat eğer bu şekilde yazarsak kodun doğru çalışıp çalışmadığını anlayamayız. Yani Sorgu_Çalıştır metodu hatırlarsanız geriye bool türünde bir değer döndürüyordu. İşte bu geriye dönen değeri okursak işlemin başarıyla gerçekleşip gerçekleşmediğini anlayabiliriz. İsterseniz buraya kadar olan kısmı kaydedip bi çalıştırın neler olduğunu gözlemleyin. Sonra da kaydet butonundaki kodu şu şekilde değiştirin.

 

   if (vt.Sorgu_Çalıştır("insert into kisiler(adi, mail, dil, dogum_tarihi) values('"+ textBox1.Text +"', '"+ textBox2.Text +"', '"+ textBox3.Text +"', '"+ textBox4.Text +"')")==true)

            {

                MessageBox.Show("İşlem başarılı", "Bildiri", MessageBoxButtons.OK, MessageBoxIcon.Information);

            }

            else

            {

                MessageBox.Show("İşlem başarısız");

            }

            vt.Listele("Select * from kisiler", dataGridView1);

 

Eğer sorgu_çalıştır metodundan geriye dönen değer true ise işlem başarıyla gerçekleşmiştir. Geriye dönen değer false ise başarısızdır. Gördüğünüz gibi mantık gayet basit ve kullanımı da çok kolay.

 

        Şimdi de sil butonuna gerekli kodumuzu yazalım:

 

            if (vt.Sorgu_Çalıştır("Delete from kisiler Where mail='"+ textBox2.Text +"'")==true)

            {

                MessageBox.Show("İşlem başarılı", "Bildiri", MessageBoxButtons.OK, MessageBoxIcon.Information);

            }

            else

            {

                MessageBox.Show("İşlem başarısız");

            }
            vt.Listele("Select * from kisiler", dataGridView1);

 

Gördüğünüz gibi kodlarda değişen hiçbir şey yok. Değişen tek şey sadece kullandığımız sql cümlesi hepsi bu.

 

        Şimdide Veri_Çek komutumuzu görelim. Ben bunu şimdilik mesaj olarak görüntüleyeceğim ama siz bir değişkene atabilir veya başka işlemlerde yaptırabilirsiniz burdaki komutu bu şekilde kullanmak zorunda değilsiniz. Bu sadece bir örnektir. Bu komutumuzu  da button nesnesine yazalım.

MessageBox.Show(vt.Veri_Çek("kisiler", 0, 1));

Veri_Çek metodundan geriye dönen değer string türündedir. Parametreler önce tablo ismi verilir  sonra satır numarası sonra alan numarası bunlar verildiğinde o tablodaki gerekli bilgi size döndürülür.

 Arkadaşlar şimdi de Oku komutunun kullanımını görelim. Önce kayıt sayısını öğrenelim. Bunun için yeni button nesnesine şu kodları yazalım:

 

 MessageBox.Show("Tablodaki kayıt sayısı " + vt.Oku("kisiler", 0).Count.ToString());


Arkadaşlar şimdi de Oku komutunu kullanarak herhangi bir alanda aramak istediğimiz veri var mı yok mu bunu sorgulayabiliriz. Bunun için yeni button nesnesine şu kodları yazın:

 

 bool bul;
            bul = vt.Oku("Kisiler", 1).Contains(textBox5.Text);
            if (bul==true)
            {
                MessageBox.Show("Aradığınız kişi kayıtlıdır.");
            }
            else
            {
                MessageBox.Show("Aradığınız kişi veritabanında kayıtlı değil");
            }


       Şimdi de oku komutunu kullanarak istediğimiz satır ve alandan nasıl bilgi alabiliriz onu göreceğiz. Fakat bu şekilde kullanmanızı tavsiye etmiyorum çünkü bu iş için biz zaten Veri_Çek komtunu yazmıştık. Fakat bir alternatif olarak düşünebilirsiniz ki bu da komuttan geriye dönen değer list of string olduğu için yani bir string listesi olduğu için buna izin veriyor. Tabi dediğim gibi Veri_Çek komutu oku komutunun bu şekilde kullanılmasından daha hızlı çalışır.

MessageBox.Show(vt.Oku("kisiler", 1)[2]); //1. sütundaki 2. satırdaki bilgi. Bu komutla Veri_Çek komtunun bir farkı yok aynı işlemi yapar fakat Veri_Çek komutu varken bunu kullanmayın çünkü bu komut Ver_Çek komutuna göre daha yavaş çalışır.


Makalemi burada sonlandırıyorum arkadaşlar, okuduğunuz için teşekkür ederim. Makalenin altından projeyle ilgili dosyaları indirebilirsiniz.


Kisiler.rar