Cuma, Kasım 18, 2005

Delphi ile Veritabanı Programlama Hakkında Önbilgi

Günümüz programlarında bilgiler veritabanı sistemleri üzerinde tutulurlar. Veritabanları tablolardan, tablolar ise satır ve sütunlardan oluşan yapılardır. Delphi içinde genellikle tablolar table, sütunlar field, satırlar ise record olarak adlandırılır. Bir delphi programıyla veritabanı arasında bilgi alışverişi yapabilmek için öncelikle veritabanında bir tablo açılmalıdır. Sonra o tabloda kullanmak istenilen sütunları tanımlamalıyız. Bunları veritabanı ile gelen programlar ile yapabiliriz. SQL Server, Oracle, Access, MySQL, Interbase yaygın kullanılan veritabanı sistemleridir.

Delphi projelerinde veritabanı sunucusuna bağlantıyı TConnection bileşeni sağlar. Veritabanından çektiğimiz bilgileri ve bu bilgiler üzerinde yaptığımız değişiklikleride TDataset bileşeni (component) tutar. Bir TDataset bileşeni veritabanına bağlanabilmek için TConnection bileşenine ihtiyaç duyar. Birçok durumda bir program için bir TConnection bileşeni yeterlidir. Projemize ekleyeceğimiz her dataset aynı connection bileşenini kullanabilir. Teoride delphi tüm verikaynakları ile bu bileşenler üzerinden çalışabilir ancak verikaynağının türüne göre özel türleri vardır. Mesela TADODataset ve TADOConnection Ado desteği olan veritabanlarına bağlanmak için kullanılan özel veri bileşenleridir. Veritabanı üzerinde bulunan bilgiler TConnection bileşeni ile çekilerek TDataset bileşenine aktarılır. TDataset üzerinde yapılan değişiklikler de aynı yoldan tekrar veritabanına yazılır.

Access kullanıyorsanız programı çalıştırarak yeni bir tablo açın adına MUSTERILER deyin ve tabloya MUSTERIADI ve MUSTERIADRESI olarak iki tane sütun (field) tanımlayın.

İlgili tabloyu tanımladıktan sonra delphi projemize bir TAdoConnection ekleyerek üzerine çift tıklıyoruz ve gelen ekrandaki bilgileri doldurarak TAdoConnection bileşenimizin veritabanına nasıl bağlanacağını ilgili parametrelerden tanımlıyoruz. Use connection string'i seçip build diyoruz ve gelen ekrandan provider sayfasına tıklayıp Microsoft JET 4.0 OLEDB Provider'i seçiyoruz. Connection sayfasına geçip "Select or Enter a Database Name" (1. seçenek) editinin yanındaki ... düğmesine tıklayarak mdb dosyamızı buluyoruz ve OK diyerek işimizi bitiriyoruz.

Şimdi Delphi projemize geçiyoruz ve yeni bir proje başlatıyoruz. Ana Formun üzerine veritabanında açtığımız tabloya karşılık gelecek bir TAdoDataset bileşeni ekliyoruz. AdoDatasetin connection özelliğini AdoConnection1 olarak belirliyoruz. Bu AdoConnection1 biraz önce eklediğimiz TConnection bileşenidir. Sonra datasetimizin CommandText özelliğine çift tıklayarak önce Tables listesine gelen tablolardan kullanmak istediğimiz tablo adına çift tıklıyoruz. İkinci adımda datasetimizde kullanmak istediğimiz sütun (field) isimlerine çift tıklıyoruz. Eğer tüm sütunları kullanmak istiyorsak sadece * 'a çift tıklıyoruz. Eğer yanlış birşey yaparsak Cancel diyerek tekrar yapabiliriz. Aslında bunu yaparken basit bir SQL cümlesi yazmış olduk. Tablomuzun adının MUSTERILER olduğunu düşünürsek sağ tarafta

SELECT * FROM MUSTERILER

gibi bir cümle oluşması lazım. Bu oluşan cümle veritabanları ile programlar arasındaki konuşma dili olan SQL'dir. Buradaki cümle "MUSTERILER Tablosundaki tüm bilgileri getir" anlamına gelir. İstersek bu cümleyi direk CommandText özelliğine yazarak da aynı sonucu elde edebiliriz. OK diyerek pencereyi kapatıyouz ve TAdoDataset'in Active özelliğini True yaparak tabloyu aktif hale getiriyoruz. Eğer Active özelliği hiç hata vermeden true oluyorsa programımız veritabanına başarıyla bağlanmış ve ilgili tabloyu kullanabilir hale gelmiş demektir. Genellikle gerçek programlarımızda datasetleri active konumunda bırakmak iyi bir fikir değildir. Bilgisayar hafızasını ve veritabanın kaynaklarını verimli kullanabilmek için datasetleri ihtiyacımız olduğunda kodla AdoDataset1.Open diyerek dataseti Active konumuna getirmek ve işimiz bittiğinde de AdoDataset1.Close diyerek kapatmak gerekir. Şimdilik deneme yaptığımız için Active özelliğini true olarak bırakalım.

Şu ana kadar veritabanından bilgi çekmekle ilgili tanımlamaları yapmış olduk. Şimdi sıra bunu kullanıcıya göstermeye geldi. Veritabanlarına bağlı çalışan programlar için TDataset bileşenleri ile çalışabilen birçok kontrol Delphi içinde standart olarak gelir. Edit, ListBox, ListView gibi forma direk yerleşebilen elemanlara kontrol diyoruz. TEdit içine yazı yazabildiğimiz bir kontoldür ve bunun veritabanları ile otomatik olarak çalışabilen türevi TDBEdit'dir. Adı TDB ile başlayan kontrollerin birçoğu veritabanından bilgi okuyabilir. Kimi kontroller tek bir tablo satırı (record, row, kayıt) ile çalışabildiği gibi kimi kontroller birden çok satırla (tablonun kendisi ile) çalışabilir. Bu kontroller ile dataset arasındaki bağlantıyı TDataSource bileşeni sağlar. Formumuza bir TDataSource bileşeni ekliyoruz ve bileşenin Dataset özelliğini AdoDataset1 olarak seçiyoruz. AdoDataset1 demin eklediğimiz TAdoDataset'tir. Artık formumuza veri kontrolleri eklemeye hazır hale geldik. Şimdi MUSTERILER tablomuzda MUSTERIADI ve MUSTERIADRESI olarak iki sütun eklemiş olduğumuzu düşünelim. Bu sütunları veritabanı programının kendisini kullanarak eklemiştik. (access kullanıyorsak access'in kendisi ile, SQL Server kullanıyorsak Enterprise Manager ile) Şimdi bu iki sütun için iki tane TDBEdit bileşeni ekleyelim ve DataSource özelliklerini Datasource1 olarak seçelim. Datasource1 demin eklediğimiz TDataSource'dir. Bu kontrollerin hangi sütunlarla çalışacağını ilgili kontrolün DataField özelliğini kullanarak belirliyoruz. Eğer bir hata yapmadıysak DataField özelliğine tıkladığımızda ilgili sütunların isimlerinin gelmesi lazım. Şu ana kadar bilgi girişi sağlayabileceğimiz kadar tanımlama yapmış olduk.

Programı kullanırken dataset'e kayıt ekle, sil, kaydet gibi komutlar vermemiz lazım. Bunlar normalde kodlar kullanarak yaparız ama şimdilik sonucu hemen görebilmemiz için forma bir
tane de TDBNavigator ekleyelim. Bunun da DataSource özelliğini datasource1 olarak seçelim. Bu bileşen dataset'e sonraki kayda git, ilk kayda git, son kayda git, kayıt ekle gibi komutlar vermemizi sağlar. Şimdi programı çalıştıralım. İlk olarak tablomuzda kayıt olmayacağı için
editlerimiz boş görünecek. Editlere birşeyler yazabilmek için önce tabloya boş bir satır eklememiz lazım. Bunu navigatordan + ya tıklayarak yapıyoruz. Sonra editlerin içine birşeyler yazalım ve tick işaretine tıklayalım. Tick işareti (check işareti) kaydet anlamı taşır. Bir kere daha + ya tıklayalım ve boş bir satır daha ekleyelim. Editler otomatik olarak boşalacak ve yeni kayıt girmek için hazır hale gelecek. Tekrar yeni bilgiler girelim ve tekrar tick işaretine (kaydet)tıklayalım. Şu anda iki satır bilgi girdik. İleri ve geri düğmelerine tıklayarak kayıtlar arasında dolanabiliriz. Bir kaydı değiştirmek için yukarı ok düğmesine tıklayarak satırı düzenleme moduna getiririz ve yaptığımız değişikliği kaydetmek için tekrar tick işaretine tıklarız. Değişikliği kaydetmek istemiyorsak çarpı düğmesine tıklayarak kaydı eski haline alırız. Şimdi birden çok kaydı düzenleyebilmek için kullanabileceğimiz TDBGrid kontrolünü deneyelim. Formdaki edit kontrollerini silerek bir TDBGrid ekleyelim ve gridin DataSource özelliğini DataSource1 olarak seçelim. Programı çalıştırdığınızda biraz önce girdiğimiz 2 kaydı görebilmeniz lazım. Navigator'u kullanarak bir üçüncü kaydı ekleyelim ve tick'e tıklayarak kaydedelim.

Bu işleri navigator kullanmadan kendimiz butonlar ekleyerek de yapabiliriz. Her düğmenin kod karşığı şunlar dır.

Navigatordaki dizilime göre:

AdoDataset1.First; İlk satıra git
AdoDataset1.Prior; Önceki satıra git
AdoDataset1.Next; Sonraki satıra git
AdoDataset1.Last; Son satıra git
AdoDataset1.Append; Satır ekle
AdoDataset1.Delete; Satır sil
AdoDataset1.Edit; Düzenleme moduna geç
AdaDataset1.Post; Kaydet
AdoDataset1.Cancel; İptal et
AdoDataset1.Refresh; Yenile (veritabanından tekrar oku)

Bir satırda değişiklik yapmak için önce dataseti edit moduna geçirmemiz gerekir. Yeni kayıt eklediğinizde dataset otomatik olarak edit moduna geçecektir. Kaydı silmek için edit moduna geçmeye gerek yoktur. Post ve Cancel komutlarından sonra edit modundan otomatik olarak çıkılır. Edit moduna geçirmek çok kullanıcılı sistemlerde ilgili satırı kilitleyecek ve başka bir kullanıcının kayıtta değişiklik yapmasını engelleyecektir. Refresh komutu ise yine çok kullanıcılı sistemlerde başka kullanıcıların yaptığı değişiklikleri görmemizi sağlayacaktır.

Şimdi forma iki tane TButton ekleyin ve butonlara çift tıklayarak birinin altına AdoDataset1.Next; öbürüne de AdoDataset1.Prior yazın. Denediğinizde navigatorla aynı şekilde çalıştığını göreceksiniz. Bu şekilde navigator olmadan da ilgili dataset komutlarını çalıştırabiliriz. Şimdi her komut için bir buton ekleyin ve butonların altına ilgili komutları yazın. Hangi butonun ne iş yaptığını anlamak içinde butonların caption özelliklerine gerekli tanımları yazın.

Gridde o an üzerinde bulunduğunuz kayıt dataset'in aktif satırıdır. Daha doğrusu aktif satır giridin değil datasetin bir özelliğidir. Datasette aktif satır neyse gridde o satırı işaretli olarak görürüz. Gridde başka bir satıra tıklarsak aslında dataset'in aktif satırını değiştirmiş
oluyoruz. Bu nedenle AdoDataset1.Delete komutu "Aktif satırı sil" anlamına gelecektir. Satır silindikten sonra aktif satır bir sonraki satır olacaktır. Eğer grid yerine edit kullandığımız bir önceki durumu düşünürsek datasette aktif satır neyse editlerde o satıra ait bilgiler
görünecektir. Datasetteki aktif satırı next, prior komutlarıyla değiştirebildiğimiz gibi Locate komutunu da kullanabiliriz.

AdoDataset1.Locate('MUSTERIADI','EMRE',[]); komutu aktif satırı muşteri adı Emre olan satıra getirecektir. Eğer boş köşeli parantezi [loPartialKey] şeklinde yazarsak o zaman EMRE ile başlayan ilk kayda gideriz. Locate komutu birden fazla sütunda da da çalışacak özelliktedir. Detaylı bilgi için help'e bakınız.

Dataset'in EOF ve BOF özellikleri de ilk veya son kayıtta olup olmadığımızı anlamak için kullandığımız özelliklerdir. Eğer ilk kayıtta isek AdoDataset1.BOF true döndürür. Eğer tablonun sonuna geldiysek EOF true olacaktır. Diğer durumlarda her ikisi de false döndürür.

Dikkat ederseniz navigatorda bazı durumlarda bazı düğmeler pasif duruma geçmekte bazı durumlarda da aktifleşmektedir. Bu şu anlama gelir. Dataset'e post diyebilmek için (tick'e tıklayabilmek için) tabloya bir kayıt eklemek veya bir kaydı edit moduna getirmek gerekmektedir. Eklediğiniz butonlardan da deneyebileceğiniz gibi bu iki durumdan biri
olmadan kendi eklediğiniz post düğmesine tıklarsanız hata alırsınız. Tıpkı ilk kayıtta olduğunuz halde prior, edit modunda olmadığınız halde cancel dediğinizde alacağınız gibi. Navigator bileşeni datasetin o anki duruma göre veremeyeceğiniz komutları takip ederek ilgili butonları pasifleştirir ancak bu özellik sizin eklediğiniz butonlarda olmayacaktır. Bu özelliği programlayabilmek için edit butonuna tıklandığında edit butonun enabled özelliğini false yapmalı, post veya cancel komutu verildiğinde de edit butonunun enabled özelliğini tekrar true yapmalısınız. Bunun bir yolu da ilgili komutu vermeden önce dataset'in state özelliğini kontrol etmektir. State özelliği datasetin o anki durumu ile ilgili bilgi almamızı sağlar. Örneğin dataseti edit moduna geçirdiğimizde AdoDataset1.State ifadesi bize dsEdit olarak dönecektir.

Projemize kodlara karşılık eklediğimiz butonlardan post butonundaki AdoDataset1.post; komutunu

if AdoDataset1.state = dsEdit then AdoDataset1.post;

olarak değiştirirseniz o zaman dataset edit modunda olmadığında post denirse hata vermesini engellemiş olursunuz. Çünkü post demeden önce datasetin dsEdit modunda olup olmadığını test etmiş oluruz. Bu kod eğer dataseti edit moduna geçirdiysek çalışacaktır ancak dataset'e yeni bir kayıt eklersek bu sefer yukarıda yazdığımız kodla kayıt yapamayacağımızı görürüz. Çünkü dataset'e bir kayıt eklediğimizde dataset dsEdit değil dsInsert moduna girer. Bu nedenle post butonun altındaki kodu

if AdoDataset1.state = dsEdit then AdoDataset1.post;
if AdoDataset1.state = dsInsert then AdoDataset1.post;

gibi iki durumu da kontrol edecek şekilde değiştirebiliriz. Bunun daha kısa yazılımı

if (AdoDataset1.state = dsEdit) or (AdoDataset1.state = dsInsert) then AdoDataset1.post;

olabilir. State özelliğini help'ten inceleyerek hangi değerler alabildiğine bakabilirsiniz. AdoDataset1.edit dediğimizde dataset'in state'i dsEdit olur. AdoDataset1.Append dediğimizde de state dsInsert olur. Diğer türlü de dsBrowse olacaktır.

Kodla veri okumak da datasetin FieldByName özelliği kullanılarak yapılır. bir buton ekleyelim ve altına

Form1.caption := AdoDataset1.FieldByName('MUSTERIADI').value;

yazalım. Bu butona tıkladığımızda formun captionunda datasetin aktif satırının MUSTERIADI sütununda yazan bilgiyi görüntüleriz. forma bir listBox ekleyelim ve ekleyeceğimiz diğer bir butonun altına şunu yazalım.

AdoDataset1.First; //ilk kayda git
ListBox1.items.clear; //listbox'u temizle

// son kayda gelene kadar çalıştır. Son kayda gelene kadar EOF özelliği false olacaktır.

while not ADODataset1.Eof do
begin
// MUSTERIADI sütununda yazan bilgiyi listbox'a ekle.
listbox1.items.add(AdoDataset1.FieldByName('MUSTERIADI').value);

// sonraki kayda git;
AdoDataset1.Next;
end;

Bu kod tablodaki tüm satırları tek tek dolaşarak MUSTERIADI sütunundaki bilgiyi listbox'a ekleyecektir. Ancak listbox datasource'ye bağlı olmadan çalıştığı ve ilgili satırları biz manuel eklediğimiz için listbox'ta yapacağımız değişiklikler dataset'i değiştirmeyecektir. Mesela griddeki gibi satırlara tıklamamız datasetin aktif satırını değiştirmez. Eğer MUSTERIADI sütununda boş kayıtlar varsa boş değeri listbox'a eklerken hata alabiliriz. Bunu engellemek için listbox'a ekleme kodunu

AdoDataset1.FieldByName('MUSTERIADI').AsString

olarak yazabiliriz. AsString ifadesi okunan değer boşsa onu boş String'e çevirecek ve listBox'a eklenebilecek hale çevirecektir. Eğer okumaya çalıştığımız değer integer (tamsayı) ise

AdoDataset1.FieldByName('MUSTERIADI').AsInteger

yazabiliriz. Bu durumda da boş kayıtlar sıfır'a dönecektir. Diğer veritipleri için de AsXXXXX ifadeleri vardır. Delphi yardımında TField özelliklerinden diğer AsXXXXX çevrimlerini görebilirsiniz. Genellikle veritipi neyse ona uygun AsXXXX ifadesini kullanınız.

Son olarak aynı özelliği kullanarak datasetin verilerini de değiştirebiliriz.

AdoDataset1.FieldByName('MUSTERIADI').value = 'EMRE';

ifadesi aktif satırın MUSTERIADI sütunundaki değerin EMRE olmasına neden olacaktır.
Tabiki bunu yapabilmek için öncelikle dataseti edit moduna geçirmemiz veya yeni bir kayıt eklememiz sonra da post komutunu çağırarak satırı kaydetmemiz gerekecektir. Bir satır edit modunda iken her sütunu değiştirdikten sonra kaydetmemize gerek yoktur. Satırda istediğimiz tüm değişiklikleri yaptıktan sonra post diyebiliriz.

AdoDataset1.Insert;
AdoDataset1.FieldByName('MUSTERIADI').value = 'EMRE';
AdoDataset1.FieldByName('MUSTERIADRESI').value = 'ANKARA';
AdoDataset1.Post;

Yeni kayıt eklemekle ilgili kodu bu şekilde yazabilirsiniz. Bu kayıt işleminden sonra aktif satır bu yeni eklediğimiz satır olacaktır.

3 yorum:

Sadettin POLAT dedi ki...

hocam yazilari aksatiyorsun
senin yazilarini bilhassa dunit , tdd hakkindaki bilgilerinden yararlanmak isteriz
haberin olsun :)

asilpol dedi ki...

Hocam bilgileriniz için çok teşekkürler mümkün mertebe yararlanmaya çalışıyorum delphiye yeni başladım sayılır ama uzun yol katettim. Bir yerde takıldım yardımcı olabilirseniz sevinirim. İzmir Emniyetinde bilgi işlem yubesinde görevli polis memuruyum. Emniyete mahsus polnet ortamında admin şifreleri ile ilgili program yapıyorum öğrenmek istediğim şu butona bastığımda o birime ait en son kayda giderek en son admin şifresini bulacak ve örneğin Dis23AlG01 olan kaydı 1 arttırarak Dis23AlG02 yapacak kod arıyorum ben beceremedim yardımcı olursanız çok sevinirim (canaslan_70@hotmail.com). Saygılar

Adsız dedi ki...

while not Adotable.eof do
begin
if Edit.text= Adotable.fieldbyname('kod').asstring
then begin
inc(counter)
end;
Adotable.next;
end;

bu sekılde kontrol saglayabılıorum ancak.Adotable.next satırımla sonuna gelıyorum lıstenın.bır dahakı bloga Adotable bos olarak gırıo.bunu duzenleyebılcegım satıra bır daha gerı nasıl getırebılırım.yardımcı olursanız sevnırım.tesekuurler