4. İLERİ DÜZEY VERİ TABANI GELİŞTİRME
4.1. VERİ BÜTÜNLÜĞÜNÜ SAĞLAMA.
Visual Basic ile veritabanı geliştirirken sağlanan önemli bir özellik de veri bütünlüğünü koruma özelliğidir. Bu ilişkisel veritabanı kullanımının temel bir gereğidir.
Visual Basic ile veritabanının veri bütünlüğünü korumak ve sağlamak için veritabanı tabloları arasında tanımlanabilen ilişkiler kullanılır. İlişki tanımlama kavramına daha önce değinilmişti. İlişki yukarıda da bahsedildiği gibi birbiriyle ilişkili alanlar barındıran iki farklı tabloya girilecek verilerin tutarlılığını sağlar. Veritabanı üzerinde bir ilişki tanımlandıktan sonra, ilişkiyi ihlal eden veri girişi DAO nesnesinin ele alınabilir hatalı bir duruma girmesini sağlar. Böylece hem veri bütünlüğü ve tutarlılığı sağlanmış olur, hem de kullanıcı böyle bir ihlalin açığa çıktığından haberdar edilir.
Veritabanı bütünlüğünü sağlamanın bir diğer yolu da bazı kurallar tanımlayarak kullanıcının belirli alanlara yanlış veriler girmesine engel olmaktır.
Veritabanı üzerinde tablolara ve alanlara uygulanabilecek birçok kural vardır.
Kuralları uygulamanın iki yolu vardır.
Veritabanı üzerinde tanımlanabilecek kuralların hepsini veritabanı motoruna bırakmak pek mümkün değildir, fakat amaç olabildiğince çok kuralı veritabanı tanımına eklemek ve kuralları veritabanı motorunun uygulamasını sağlamak olmalıdır.
Şu ana kadar veritabanı üzerinde bütünlüğünü sağlamaya yönelik bir çok kural tanımladık bunlar;
Bu kuralların yanısıra aşağıdaki kuralları da veritabanına eklemek mümkündür.
Yukarıda belirtilen özelliklerden Required ve AllowZeroLength özellikleri Boolean türünden özelliklerdir.
ValidationRule özelliği geçerli bir Visual Basic ifadesini belirtir. Bu ifadede kullanıcının tanımladığı fonksiyonlar, SQL kümeleme fonksiyonları, bir sorgu, başka bir tablonun alanı yer alamaz.
Şimdi veritabanı bütünlüğünü korumak için kural tanımlarını örneklemek için daha önce kullanmış olduğumuz PERSONEL veritabanı üzerinde bazı kurallar tanımlayalım ve bunları veritabanı üzerine uygulayalım.
1. Önce kuralları bir tablo halinde gösterelim.
Tablolar Alanlar Özellik Değer Personel_bil sicno Required True ad_soyad Required True dtar Required True dtar ValidationRule Koşul1* dyer Required True personel_gorev sicno Required True CYIL Required True CYIL ValidationRule Koşul2* gno Required True mno Required True derece Required True gorevler gno Required True GADI Required True meslekler mno Required True MADI Required True
Koşul1: IIf(Year(dtar)>1930,
Year(dtar)<1976, False)
Koşul2: IIf(CYIL>=0, CYIL<68, False)
2. Yeni bir proje yaratın. Aşağıdaki nesneleri ekleyin.
Form Name frmKurallar Caption KURAL EKLEME PROGRAMI BorderStyle 3-FixedDialog CommonDialog Name dlg CommandButton Name cmdKural Caption &Kural Ekle CommandButton Name cmdVT Caption &Veritabanı aç Label Name lblSonuc Autosize True Forma aşağıdaki kodu girin.
Private db As Database
Private Sub cmdKural_Click()
On Error GoTo phata:
KuralEkle
lblSonuc.Caption = "KURALLAR EKLENDİ"
Exit Sub
phata:
MsgBox Err.Description, vbExclamation
End Sub
Private Sub cmdVT_Click()
Dim dosya As String
dlg.InitDir = App.Path
dlg.DefaultExt = "mdb"
dlg.DialogTitle = "Veri Tabani Aç"
dlg.Filter = "VB Veritabani(*.mdb)|*.mdb"
dlg.FilterIndex = 1
dlg.Flags = cdlOFNHideReadOnly Or cdlOFNFileMustExist _
Or cdlOFNPathMustExist
dlg.CancelError = True
dlg.ShowOpen
dosya = dlg.filename
Set db = DBEngine.Workspaces(0).OpenDatabase(dosya)
cmdKural.Enabled = True
cmdVT.Enabled = False
Exit Sub
phata:
dosya = ""
End Sub
Private Sub KuralEkle()
Dim td As TableDef
Dim fld As Field
For Each fld In db.TableDefs("personel_bil").Fields
fld.Required = True
Next
For Each fld In db.TableDefs("personel_gorev").Fields
fld.Required = True
Next
For Each fld In db.TableDefs("gorevler").Fields
fld.Required = True
Next
For Each fld In db.TableDefs("meslekler").Fields
fld.Required = True
Next
Set fld = db.TableDefs("personel_bil").Fields("dtar")
fld.ValidationRule = "IIf(Year(dtar)>1930, Year(dtar)<1976, False)"
fld.ValidationText = "Dogum tarihi 1930-1976 arasinda olmali"
Set fld = Nothing
Set fld = db.TableDefs("personel_gorev").Fields("CYIL")
fld.ValidationRule = "IIf(CYIL>=0, CYIL<68, False)"
fld.ValidationText = "Çalistigi yil 0-68 arasi olmali"
Set fld = Nothing
cmdKural.Enabled = False
End Sub
Yukarıdaki kodda önemli olan KuralEkle fonksiyonudur. Burada, kural tanımlarımızın gereği tabloların bütün alanlarının Required özellikleri True yapılmıştır. Bunun anlamı, ‘veritabanının hiç bir tablosundaki hiç bir alan boş geçilemez’ dir.
Bu kuraldan başka iki tane de farklı kural tanımlanmıştır. Bu kurallar doğum tarihinin yılını ve kişinin kurumda çalıştığı yıl sayısını sınırlayan kurallardır.
Program çalıştığında aşağıdaki form çıkar. Başlangıçta bu formun üstündeki “KURALLAR EKLENDİ” yazısı yoktur ve sadece veritabanı aç butonu aktif haldedir. Bu butona basıldığı anda standart Windows95 Open Dialog kutusu çıkar ve buradan veritabanının adının bulunmasına olanak tanınır. Daha sonra veri tabanı açılır, veritabanı açma butonu gri hale getirilir, kural ekleme butonu aktif hale gelir. Kurallar eklendikten sonra bu buton da gri hale gelir.
4.2. ÇOK KULLANICILI VERİTABANLARI VE GÜVENLİK
Eğer bir ağ üzerinde, birden fazla kullanıcıya hizmet veren uygulamalar geliştirilecekse, bu uygulamanın verileri kullanıcılar arasında etkin bir biçimde paylaştırması gerekir. Bu bölümde, çok kullanıcılı uygulamalar geliştirilirken dikkat edilmesi gereken konuları içermektedir. Çok kullanıcılı sistemlerde verilere erişimin denetlenmesi için gerekli olan kilitleme stratejileri ve bu kilitlemelerin çok kullanıcılı bir ortamda ele alınışına değinilecektir.
Bu bölümde Microsoft Jet veritabanı motoru bağlamında çok kullanıcılı veritabanı kavramı ele elınacaktır, ODBCDirect bağlamında değil. ODBCDirect yöntemi ile uygulamalar doğrudan ODBC veritabanlarına erişebilir. Bu erişim için Jet veritabanı motoruna ihtiyaç yoktur. Bu konuya daha sonra değinilecektir.
Bir programın çok kullanıcılı olabilmesi için;
olmak üzere iki yaklaşım sözkonusudur.
Bu yaklaşımlardan ilki ağ trafiğinde bir artışa neden olur.
Ağ üzerinden erişim daha yavaş olduğu için uygulamanın bazı kısımlarını kullanıcı bilgisayarında tutmak her zaman için hız avantajı sağlar. Bu bağlamda uygulamanın kesimleri iki kategori altında toplanabilir.
Statik kesimler : Programın çalışmasını sağlayan .dll ve .exe dosyalarıdır. Uygulamadaki, formlar, raporlar, program kodları da statik kesimlerdir.
Aktif kesimler : Çok kullanıcılı bir ortamda kullanıcıların erişeceği gerçek verilerin tutulduğu dosyalardır. Bunlar Jet veritabanları veya dış veritabanları olabilir.
Statik kesimlerin özellikleri:
Aktif kesimlerin özellikleri:
İki düzeyli veritabanı yaklaşımı sözkonusu olduğunda, her kullanıcının kendi bilgisayarında;
Microsoft Jet veritabanının çok kullanıcılı modeli aşağıdaki gibidir.
Workgroup bilgi dosyası, kullanıcı, grup ve password bilgilerini ve kullanıcı ile ilgili başka bilgileri tutan bir veritabanıdır. Bu dosya ağ sunucusunda veya her bir kullanıcı bilgisayarında tutulabilir. Herbir kullanıcı bilgisayarında tutulduğunda güvenlik bilgileri değiştiğinde değişiklikleri anında güncelleme gerekliliği vardır.
Kilitleme bilgi dosyası, kilitlenmiş olan tutanaklarla ilgili bilgileri tutar. Veri tabanı açıldığında bu kütük yoksa jet veritabanı motoru bu dosyayı yaratır. Paylaşımlı olarak açılan herbir veritabanı dosyası için bir kilitleme dosyası tutulur. Bu dosyaya verilen isim veritabanı dosyasının ismiyle aynıdır. Bu dosya veritabanı dosyası ile aynı dizinde tutulur.
Microsoft Jet tarafından desteklenen ağ-sunucuları şunlardır:
Microsoft Windows NT and Windows 95 networks
Banyan VINES 5.52
DECnet 4.1
LANtastic 5.0
Novell NetWare 3.x and 4.x
OS/2 LAN Manager, 2.1 and 2.2
Tek kullanıcılı bir ortamda çalışırken veriler tamamen kullanıcıya ait olduğundan hiç bir sorun yoktur. Fakat çok kullanıcılı ortama geçildiğinde çatışmalar sözkonusudur.
Bu çatışmalar kilitleme olanakları sayesinde engellenmektedir. Bu olanaklar birçok kullanıcının aynı anda veritabanı üzerinde işlem yapmasına olanak tanır.
Paylaşımlı bir veritabanı üzerinde işlem yapılırken, değişiklik yapılacağı zaman veri kilitlenir. Bu sırada başka kullanıcılar bu veriyi okuyabilir fakat değişiklikler yapamaz. Jet veritabanı motoru üç düzeyde kilitleme olanağı sağlamaktadır.
Dışlayan mod : Tüm kullanıcıların veritabanına erişimlerini engeller.
Bu en kısıtlayıcı moddur.
RecordSet kilitleme : Bir Recordset nesnesinin belirttiği bir tabloyu table-read
veya table-write kilitlerini kullanarak kilitler.
Sayfa kilitleme : Üzerinde değişiklik yapılmakta olan 2048 byte(2K)
uzunluğundaki veriyi kilitler.
Hangi tür kilitlemeyi kullanacağımızı belirlemek için, sağlanacak olan paralellik düzeyi dikkate alınmalıdır. En yüksek paralellik için en düşük kısıtlamaya sahip kilitlenme kullanılmalıdır. Bunun yanısıra tüm verilere çabuk bir şekilde erişim için ise dışlayan kilitleme tercih edilmelidir.
Veritabanı üzerinde büyük değişiklikler yapılacaksa dışlayan mod tercih edilmelidir.
Tek kullanıcılı bir ortamda veritabanı erişimleri dışlayan modda olur, çünkü veritabanını kullanacak başka kimse zaten yoktur. Çok kullanıcılı sistemlerde veritabanı paylaşımlı modda kullanılmak üzere düzenlenmelidir. Bu tür ortamlarda kullanıcıların veritabanını dışlayan modda açmaları engellenmelidir. Bunun için kullanıcılara veritabanı üzerinde haklar tanımlanır. Bir kullanıcı bu haklar çerçevesinde veritabanına erişir.
Tutanak bazında kilitleme sözkonusu ise, veritabanı paylaşımlı modda açılır. Veritabanı paylaşımlı modda açıldığında Jet veritabanı motoru çatışmaları ele alır ve tutarsız durumlara girilmesini engeller.
Aşağıdaki kod parçası, veritabanının paylaşımlı modda açılmasını örneklemektedir.
Function VTac(vt As Database, dosya As String, dislayan as Boolean) As Integer
On Error Resume Next
Set vt = OpenDatabase(dosya, dislayan)
Select Case Err
Case 0: VTac = 0 'Başarılı
Case 3033: VTac = 1 'Erişim Hakkı yok
Case 3343: VTac = 2 'Hatalı Veritabanı
Case 3044: VTac = 3 'Hatalı Dizin Adı
Case 3024: VTac = 4 'Hatalı Dosya Adı
Case Else: VTac = 5 'Başarısız
End Select
Err = 0
End Function
Bu kod sayesinde veritabanı verilen parametreye göre paylaşımlı veya paylaşımsız açılmakta ve bu açma işleminin sonucu çağrıldığı ortama 0-5 arasında bir sayı olarak döndürülmektedir. Bu fonksiyonun kullanımı şu şekilde olabilir.
Dim Sonuc As Integer
Dim db as Database
Sonuc = VTac(db,"PERSONEL.MDB", False)
Bazen bir veritabanını sadece okunabilir modda açmak gerekebilir. Bu mod paylaşımlı modun değiştirilmiş biçimidir. Bir veritabanını sadece okunabilir modda açmak için şu kod kullanılır.
Vt = OpenDatabase("PERSONEL.MDB", False, True)
Veritabanı sadece okunabilir modda açıldığı zaman hiç bir çatışmaya neden olunmadan veritabanı dolaşılabilir.
Recordset kilitleme yöntemiyle, Recordset nesnesinin ilgili olduğu tutanakların kilitlenmesi sağlanabilir. Bu tür kilitleme ancak Dynaset türü Recordset nesnelerinde mümkündür. Veritabanı paylaşımlı modda açıldıktan sonra Recordset kilitlemeyi sağlamak için OpenRecordset metodu birkaç parametre daha eklenerek çağrılır.
Kilitlemeyi sağlamak için,
Aşağıdaki kod kesiminde bir Recordset Yapısının dışlayan modda nasıl açılabileceğini görmek mümkündür.
Function TabloAc(vt As Database, rs As Recordset, Tablo As String) As Integer
Set rst = dbs.OpenRecordset(Tablo, _
dbOpenTable, dbDenyRead + dbDenyWrite)
Select Case Err
Case 0: OpenTableExclusive = 0 'Başarılı
Case Else: OpenTableExclusive = 1 'Başarısız
End Select
Err = 0
End Function
Burada Recorset yapısı verilen 3. Parametre ile hem yazmaya hem okumaya karşı kilitlenmiştir. Bu parametre belirtilmezse Sayfa Kilitleme yöntemi kullanılır. Bu yöntemle başka kullanıcıların veriyi okumaları engellenmez.
Recordset açılırken eğer başka kullanıcılar tarafından kullanılan tutanaklara kilitleme yapılmaya çalışılıyorsa aşağıdaki hata oluşur.
error 3262:"Couldn't lock table <a>; currently in use by user <b> on machine <c>."
Bu hatada a, bir tablo ismi, b, bir kullanıcı ismi, c, ağdaki bir makinenin ismidir. Bu hatayı ele almak için bir süre beklyip kilitlemeyi tekrar denemek gerekir.
Sayfa Kilitleme yöntemiyle, değiştirilecek tutanakların kilitlenmesi mümkündür. Bir seferde 2048 byte uzunluğundaki veri bu yöntemle kilitlenebilir. Bu yöntemle veriler kilitlendiğinde diğer kullanıcılar veriyi okuyabilir fakat değiştiremez. Sayfa kilitlemeyi denetlemek için Recordset nesnesinin LockEdits özelliği kullanılır. Sayfa kilitleme modları iki tanedir. Bunlar Pesimistic ve Optimistic olarak adlandırılır.
Pessimistic Kilitleme ile, şu anda değiştirilecek olan tutanağın bulunduğu sayfa, Edit metodu kullanıldığı anda kilitlenir. Bu kilitleme değişiklikler tamamlanıncaya kadar devam eder.
Bu kilitleme yönteminin temel avantajı, kilitleme işlemi yapıldıktan sonra kilitlenen sayfadaki tutanaklarla yapılan işlemlerde çatışma olmayacağının garanti edilmesidir. Ayrıca, pessimistic kilitleme veritabanındaki tutanakların en son durumunu elde etmenin en emin yoludur. Çünkü bir kere kilitleme yapıldıktan sonra hiç bir kullanıcı bu verileri değiştiremez.
Dezavantajı ise, sayfanın uzun süre kilitli kalma riskidir. Örneğin bir kullanıcı sayfayı kilitler ve uzun süre bilgisayarı boş bırakırsa bu sayfada uzun bir süre boyunca kimse değişiklik yapamaz.
Optimistic Kilitleme yöntemiyle, sayfa sadece değişiklikler kaydedileceği zaman kilitleme yapılır. Böylece sayfanın kilitli kaldığı süre önemli ölçüde azalmış olur.
Bu kilitleme yönteminin dezavantajı da, yapılan değişikliklerin kaydedilebileceğinden emin olamamaktır. Çünkü değişikliğe başlandığında gerçek bir kilitleme yapılmaz. Bu esnada başka bir kullanıcı tutanağı pesimistic kilitleme yöntemiyle kilitlerse, yapılan değişiklikler kaydedilmeye çalışıldığında erişim hakkı olmadığı için bu işlem başarısız olacaktır.
Optimistic Kilitlemeyi kullanmak için;
Değişiklikler kaydedileceği zaman veritabanı üzerinde Pesimistic kilitleme otomatik olarak yapılır.
Sayfa Kilitleme sırasında çıkan hatalar:
3188. Daha önce kilitlenmiş sayfa, kaydetme yapılamaz.
3197. Aynı anda değişiklik yapmaya kalkışma sonucu oluşan çatışma.
3260. Daha önce kilitlenmiş sayfa, kilitleme yapılamaz.
Örnek : Sayfa kilitlemeyi örneklemek için daha önce kullanılan PERSONEL
veritabanının PERSONEL_BIL tablosunu kullanalım.
değiştirin. İsimlerini de buna uygun hale getirin.
Frame Name Frame1
OptionButton Name Option1
Caption Pessimistic Kilitleme
OptionButton Name Option2
Caption Optimistic Kilitleme
5. Formun kod kısmına aşağıdaki kodu ekleyin.
Option Explicit
Private db As Database
Private rs As Recordset
Private degisiyor As Boolean
Private Const PESSIMISTIC = True
Private Const OPTIMISTIC = False
Private Sub cmdDeg_Click()
Dim i As Integer
On Error GoTo phata
If degisiyor Then TutanakGunle
rs.Edit
degisiyor = True
cmdDeg.Enabled = False
cmdKaydet.Enabled = True
For i = 0 To 3
Text1(i).Enabled = True
Next i
Exit Sub
phata:
Select Case Err.Number
Case 3260: MsgBox "Tutanak Kilitli", vbExclamation, "degistirme"
Case Else: MsgBox Err.Description, vbExclamation, "degistirme"
End Select
End Sub
Private Sub cmdKaydet_Click()
TutanakGunle
End Sub
Private Sub cmdYenile_Click()
If degisiyor Then TutanakGunle
rs.Requery
rs.MoveNext
rs.MovePrevious
VeriAl
End Sub
Private Sub Form_Load()
Dim dosya As String
On Error GoTo phata
dosya = App.Path & "\PERSONEL.MDB"
Set db = DBEngine.Workspaces(0).OpenDatabase(dosya)
Set rs = db.OpenRecordset("personel_bil", dbOpenDynaset)
If rs.EOF And rs.BOF Then
MsgBox "Bos Tablo", vbExclamation, "HATA"
Unload Me
Else
rs.MoveFirst
VeriAl
End If
Option1 = True
pcik: Exit Sub
phata:
MsgBox Err.Description, vbExclamation
Unload Me
Resume pcik
End Sub
Private Sub Form_Unload(Cancel As Integer)
Set db = Nothing
Set rs = Nothing
End Sub
Private Sub Command1_Click(Index As Integer)
On Error GoTo phata
If degisiyor Then TutanakGunle
Select Case Index
Case 0: rs.MoveFirst
Case 1:
rs.MovePrevious
If rs.BOF Then rs.MoveFirst
Case 2:
rs.MoveNext
If rs.EOF Then rs.MoveLast
Case 3: rs.MoveLast
End Select
VeriAl
pcik: Exit Sub
phata:
MsgBox Err.Description, vbExclamation
Resume pcik
End Sub
Private Sub Option1_Click()
If degisiyor Then TutanakGunle
rs.LockEdits = PESSIMISTIC
End Sub
Private Sub Option2_Click()
If degisiyor Then TutanakGunle
rs.LockEdits = OPTIMISTIC
End Sub
Private Sub VeriAl()
Dim i As Integer
Text1(0).Text = rs!sicno
Text1(1).Text = rs!ad_soyad
Text1(2).Text = rs!dyer
Text1(3).Text = rs!dtar
For i = 0 To 3
Text1(i).Enabled = False
Next i
cmdDeg.Enabled = True
cmdKaydet.Enabled = False
degisiyor = False
End Sub
Private Sub TutanakGunle()
On Error GoTo phata:
rs!sicno = Text1(0)
rs!ad_soyad = Text1(1)
rs!dyer = Text1(2)
rs!dtar = Text1(3)
VeriAl
Exit Sub
phata:
Select Case Err.Number
Case 3260: MsgBox "Tutanak Kilitli", vbExclamation, "Kaydetme"
Case Else: MsgBox Err.Description, vbExclamation, "Kaydetme"
End Select
End Sub
Programın çalışması aşağıdaki gibi olacaktır.
Kodu açıklayacak olursak; form yüklenirken veritabanı Recordset yapısı açılıyor. Değiştir butonuna basıldığında veritabanı üzerinde değişiklik yapma başlatılıyor. Bu durumda tutanak kilitleme önem kazanmaktadır.
Yenile butonuyla aktif tutanak yeniden gösteriliyor. Böylece son yapılan değişikliklerin görülmesi sağlanabilir.
VeriAl yordamında veriler metin kutularına alınıyor. TutanakGunle yordamında ise değiştirilmiş olan veriler veritabanı üzerine kaydediliyor.
Şimdi yukarıda anlatılan kilitleme mekanizmasını denemek için bir program hazırlanmış oldu. Bu program kullanılarak optimistic ve pesimistic kilitleme arasındaki fark görülebilir.
Bu programın başka kopyalarını çalıştırarak çok kullanıcı ortam benzetimi yapılabilir.
4.3. DIŞ (EXTERNAL) VERİTABANLARINA ERİŞİM
Microsoft Jet veritabanı motoru Microsoft Access veritabanları üzerinde çalışır. Bunun örneklerini şimdiye kadar gördük. Bu veritabanlarından başka bir çok veritabanının da Jet veritabanı motoru tarafından desteklendiği daha önce belirtilmişti. Bu bölümde bunun gerçekleştirimi örneklenecektir.
Microsoft Access veritabanı olmayan tüm veritabanları burada Dış(External) veritabanı olarak adlandırılmaktadır. Bu veritabanları üzerinde işlem yapılırken bazı kısıtlamalar olmasına rağmen yine de bir çok kullanışlı metot ve özellik sunulmaktadır.
Dış veritabanları iki sınıfta toplanır. Bunlar ISAM ve ODBC veritabanlarıdır.
ISAM veritabanlarına erişim için üç yol vardır.
Örnek. DAO kullanarak Microsoft Excel veritabanlarına erişim.
Excel vritabanlarına DAO kullanarak erişim yapılırken bazı kısıtlamalar sözkonusudur. Bunlar;
- Satırlar silinemez
- Formül içeren hücreler silinemez ve değiştirilemez
- Indeks yaratılamaz
- Şifrelenmiş excel veritabanları kullanılamaz.
Bunların dışında Excel veritabanları tıpkı Access veritabanıymış gibi kullanılır. (Dış veritabanları için var olan bazı temel kısıtlamalar dışında)
Örnek :
Form Name frmPBil Caption EXCEL VERITABANI ListView Name ListView1 View 3-lvwReport CommandButton Name cmdEkle Caption &Ekle CommandButton Name cmdDeg Caption &Değiştir CommandButton Name cmdYenile Caption &Yenile CommandButton Name cmdBak Caption E&xcel’de Bak CommandButton Name cmdKapat Caption &Kapat CommandButton Name cmdTamam Caption &Tamam CommandButton Name cmdIptal Caption İ&ptal Textbox Name Text1 (Control array)
Formun tasarım esnasındaki görünüşü aşağıdaki gibi olmalıdır.
Aşağıdaki kodu formun kod kesimine yazın.
Option Explicit
Private db As Database
Private rs As Recordset
Private durum As Integer
Private Const EKLEME = 0
Private Const DEGISTIRME = 1
Private aktifHucre As ComctlLib.ListItem
Private Sub cmdBak_Click()
Set rs = Nothing
Set db = Nothing
Shell "d:\msoffice\office\excel.exe " & App.Path & "\personel.xls", _
vbNormalFocus
End Sub
Private Sub cmdDeg_Click()
Dim i As Integer
rs.MoveFirst
For i = 1 To ListView1.SelectedItem.Index - 1
rs.MoveNext
Next i
Text1(0) = rs!sicno
Text1(1) = rs!ad_soyad
Text1(2) = rs!dtar
Text1(3) = rs!dyer
EkleGoster
durum = DEGISTIRME
End Sub
Private Sub cmdEkle_Click()
Dim i As Integer
For i = 0 To 3
Text1(i) = ""
Next
EkleGoster
durum = EKLEME
End Sub
Private Sub cmdIptal_Click()
EkleSakla
End Sub
Private Sub cmdKapat_Click()
Unload Me
End Sub
Private Sub cmdTamam_Click()
If durum = EKLEME Then rs.AddNew Else rs.Edit
rs!sicno = Text1(0)
rs!ad_soyad = Text1(1)
rs!dtar = Text1(2)
rs!dyer = Text1(3)
rs.Update
ListeDoldur
EkleSakla
End Sub
Private Sub cmdYenile_Click()
ListeDoldur
End Sub
Private Sub Form_Activate()
DoEvents
ListeDoldur
End Sub
Private Sub Form_Unload(Cancel As Integer)
Set db = Nothing
Set rs = Nothing
End Sub
Private Sub EkleSakla()
Me.Height = 3700
NesneGunle True
End Sub
Private Sub EkleGoster()
Me.Height = 5265
NesneGunle False
End Sub
Private Sub NesneGunle(idurum As Boolean)
Dim i As Integer
cmdEkle.Enabled = idurum
cmdDeg.Enabled = idurum
cmdYenile.Enabled = idurum
cmdBak.Enabled = idurum
cmdKapat.Enabled = idurum
For i = 0 To 3
Text1(i).Enabled = Not idurum
Next
cmdTamam.Enabled = Not idurum
cmdIptal.Enabled = Not idurum
End Sub
Private Sub ListeDoldur()
Dim fld As Field
Dim alanSay As Integer
Dim alanGen As Single
Dim listeEl As ListItem
EkleSakla
Set db = OpenDatabase(App.Path & "\personel.xls", False, False, _
"Excel 8.0;HDR=YES;")
Set rs = db.OpenRecordset("personel_bil$")
With ListView1
.ColumnHeaders.Clear
.ListItems.Clear
For Each fld In db.TableDefs("personel_bil$").Fields
alanGen = TextWidth(fld.Name) + 500
.ColumnHeaders.Add , , fld.Name, alanGen, vbLeftJustify
Next fld
.ColumnHeaders.Item(4).Width = .ColumnHeaders.Item(4).Width + 400
.ColumnHeaders.Item(2).Width = .ColumnHeaders.Item(2).Width + 400
End With
rs.MoveFirst
While (Not rs.EOF)
Set listeEl = ListView1.ListItems.Add(, , CStr(rs.Fields(0)))
For alanSay = 1 To rs.Fields.Count - 1
listeEl.SubItems(alanSay) = rs.Fields(alanSay)
Next alanSay
rs.MoveNext
Wend
Set aktifHucre = listeEl
Set listeEl = Nothing
End Sub
Program biraz incelendiğinde görülecektir ki erişimin daha önceki veritabanı erişimlerden hiç farkı yoktur. Tek fark veritabanını açma aşamasındadır. Excel için bir diğer fark da Tablo isimlerinin sonuna “$” işaretinin konması gerekliliğidir. Programın çalışması aşağıdaki gibi olacaktır.
Program ilk çalıştığında formun alt kısmı görülmez. Bu özellik formun Height özelliği çalışma esnasında değiştirilerek sağlanmıştır. Ekle ve Değiştir butonlarına basıldığında alt taraf görünür. Bu kısım veri girişi yapmaya yardımcı olur. Değişiklik veya ekleme yapıldıktan sonra alt taraf tekrar görünmez hale getirilir.
4.4. ODBC VERİTABANLARINA ERİŞİM
Microsoft Jet veritabanı motoru ve DAO kullanarak ODBC verilerine erişim için iki yol vardır. Bunlar;
Microsoft Jet önemli bir işlevselliğe sahiptir. Bağlantıların kurulması ve yönetilmesi, sorguların Veritabanı Sunucusu tarafından kabul edilebilir biçimlere dönüştürülmesi ve geri döndürülen verinin işlenmesi gibi önemli özellikler sağlar.
Bazı durumlarda Jet motorunu devreden çıkarıp DAO nesnelerinin doğrudan ODBC sürücüsüyle ilişki kurması gerekebilir. Bu ODBCDirect aracılığıyla gerçekleştirilir.
Jet veritabanı motorunun ve ODBCDirect yöntemlerinden herbirinin kendi çapında sağladığı avantajlar vardır. Aynı anda her ikisini birden kullanmak da mümkündür.
Microsoft Jet tarafından sağlanan ve ODBCDirect ile yapılamayacak olanlar:
Eğer bütün bu özelliklere ihtiyaç duyulmuyorsa ODBCDirect kullanılabilir. Ayrıca her iki yöntemin aynı anda kullanılabileceği de unutulmamalıdır.
ODBCDirect, ODBC API kullanarak DAO nesneleri aracılığıyla veritabanına doğrudan erişimi sağlar. ODBCDirect kullanarak kullanıcı bilgisayarında en az işlemler yapılarak veritabanı erişimi yapmak mümkündür. Sağladığı avantajlar:
4.4.1. ODBC VERİLERİNE MİCROSOFT JET KULLANARAK ERİŞİM
ODBC veritabanlarına erişim için kullanılan bu iki yöntemin Visual Basic ile nasıl gerçekleştiğini görelim.
Sunucuya bağlanma.
ODBC sunucusuna bağlanmak için 3 yol vardır.
Tablolara Bağ Oluşturma
Veritabanını açmaktan daha etkin bir yöntemdir. Böylece bu tablolar üzerinde Jet veritabanında yapılıyormuş gibi sorgu yapmak mümkündür. Veri tabanını açmak ilk bakışta daha hızlı gibi görünebilir, fakat tablolara her erişim için veritabanına tekrar erişim gerekir. Bu yöntem tabloların genel bilgilerini bir yerde saklar ve veritabanına erişim miktarını azaltır.
Dikkat edilmesi gereken bir konu ise sunucu tarafından tablo yapısında yapılan değişikliklerin tutarsızlığa neden olabileceğidir. Çünkü bu yöntemle tablo yapısının bir kopyası kullanıcı bilgisayarında tutulur ve sorgularda tutulan bu yapı kullanılır. Değişiklik olduğunda tekrar bağ oluşturmak gerekir.
SQL sorgu sonuclarına (view) bağ kurma ve yapay indeks oluşturma
Eğer sunucu SQL sorgu sonuclarını tutan tablo yapılarını destekliyorsa bu yapılara bağ kurmak mümkündür. Bu tablo yapıları için yapılan işlemler sunucuya aittir. Eğer sunucu bu yapılarda değişiklik yapmaya izin veriyorsa bu yapılar üzerinde indeks tanımlama da yapılabilir. Böylece sorgu sonuçlarına, herhangi bir satırı belirleyici özelliğe sahip bir alan kullanarak kolayca erişim sağlanır.
Örneğin PERSONEL veritabanı üzerinde “Yüksekokul mezunu personelin SicilNo, Ad ve Soyad, Görevi bilgilerinin listesi” sorgusunun sonucu Yuksek adıyla bir tablo yapısında tutulsun. Bu yapıya kurulan bağ ise Yıksek1 olsun. Burada SicilNo hala tutanağı belirleyen bir alan olduğundan bunu bir indeks olarak kullanabiliriz. Bunun için aşağıdaki SQL deyimi kullanılabilir.
CREATE UNIQUE INDEX Index1 ON Yuksek1(sicno)
Bu sunucuya gönderilen bir sorgu olmadığı için indeks sadece yapay bir indeks olarak kullanılır. Sunucu üzerinde böyle bir indeks yoktur.
DAO kullanarak ODBC verilerine erişim
DAO kullanarak ODBC verilerine erişmek için;
1. Windows Control Penel penceresinden 32bit ODBC seçeneğini kullanarak ODBC veri kaynağı ile ilgili ayarları yapın ve bir veri kaynağı ismi (DSN) atayın
2. Veri kaynağını temsil eden bir bağlantı (connect) metnı tanımlayın.
3. Yukarıda tanımlanan bağlantı metnini kullanarak TableDef nesnesi yaratın.
4. Bu TableDef nesnesini TableDefs kümesine ekleyin.
5. Bu bağlı tablo üzerinde bit Recorset açın. Bu Recorset yapısı ODBC veri kaynağının verilerini barındırır. Recordset nesnesinin özellikleri kullanılarak bu veriler üzerinde işlem yapmak mümkündür.
Şimdi bu adımları açıklayalım.
- Control panel penceresinden 32bit-ODBC seçeneğini seçin.
- Add düğmesine basıp bir ODBC sürücüsü seçin.(Ms SQL server)
- Bir DSN adı yazın(Personel)
- Veritabanı ile ilgili bir açıklama yazın.(abc kurumunun personeli)
- Sunucunun adını yazın.(vtSunucu)
- Veritabanının ağ adresini yazın.
Bu metin birbirinden noktalı virgülle ayrılmış ODBC sürücüsünün bağlantıyı sağlaması için kullanılan birtakım değerlerden oluşan bir satırdır. Ilk değer “ODBC;” şeklinde olmalıdır. Örneğin;
ODBC;UID=mustafa;pwd=mmtt12;DSN=Personel
Bu satırda bazı bilgiler eksik kalırsa ODBC sürücüsü eksik bilgilerin girişi için bir dialog kutusu çıkarır.
3,4,5. Bağlı tablo oluşturma.
Aşağıdaki fonksiyon bağlı tablo oluşturarak personel veritabanında “Ankara” doğumlu personel sayısını döndürür.
Public Function ankSay() As Long
Dim db As Database, rs As Recordset
Dim strBag As String, tdf As TableDef
Dim say As Long
strBag = "ODBC;DSN=Personel;UID=mustafa;" & _
"PWD=mmtt12;DATABASE=Personel"
Set db = OpenDatabase(App.Path & "\Personel.mdb")
On Error Resume Next
db.TableDefs.Delete "bPers"
db.TableDefs.Refresh
On Error GoTo phata
Set tdf = db.CreateTableDef("bPers")
tdf.Connect = strBag
tdf.SourceTableName = "personel_bil"
db.TableDefs.Append tdf
db.TableDefs.Refresh
Set rs = db.OpenRecordset("bPers", dbOpenForwardOnly)
Do Until rs.EOF
If Trim$(rs!dyer) = "Ankara" Then say = say + 1
rs.MoveNext
Loop
rs.Close
db.Close
ankSay = say
Exit Function
phata:
MsgBox "Error " & Err & ": " & Error
Exit Function
End Function
Bu örnekte PERSONEL_BIL tablosu forward-only bir Recordset yapısıyla açılmıştır. Bağlı ODBC tablolarının kullanım açısından daha önce kullanılmış olan Jet veritabanı motoru tablolarından bir farkı yoktur. Örneğin aşağıdaki sorgu bağlı bir tablo üzerinde çalıştırılabilir.
Dim db As Database, qdf As QueryDef
Set db = db1 'Kullanılmakta olan bir veritabanı
Set qdf = db.CreateQueryDef("bPers")
qdf.SQL = "DELETE FROM bPers WHERE dyer = ' Ankara'"
qdf.Execute
Bu kod daha önce yaratmış olduğumuz bağlı tablodan “Ankara” doğumlu olan personeli siler.
SQL sorgularını doğrudan sunucuya gönderme
ODBC veritabanı üzerinde SQL sorguları Jet veritabanı motoru kullanılarak da gerçekleştirilebilir fakat doğrudan sunucu üzerinde çalıştırılmaları işlemlerini daha hızlı yapılmasını sağlar.
Bu sorgular herhangi bir yorumlama yapılmadan doğrudan sunucuya gönderilir. Sorgular iki kesimden oluşur, SQL sorgu deyimi ve ODBC bağlantı metni. SQL deyimleri sunucunun kabul ettiği türden olmalıdır, Visual Basic deyimleri içermemelidir.
Avantaj ve dezavantajları:
Bu tür sorgular aşağıdaki gibi bir kodla çalıştırılabilir.
Dim db As Database, qdf As QueryDef
strBag = "ODBC;DSN=Personel;UID=mustafa;" & _
"PWD=mmtt12;DATABASE=Personel"
Set db = db1 'Kullanılmakta olan bir veritabanı
Set qdf = db.CreateQueryDef("")
qdf.SQL = "DELETE FROM bPers WHERE dyer = ' Ankara'"
qdf.Connect = strBag
qdf.Execute
Burada verilen Connect özelliği sorgunun doğrudan ODBC sunucusuna gönderilmesini sağlar.
Doğrudan sunucuya gönderilen sorgular aşağıdaki şekilde de çalıştırılabilir.
strBag = "ODBC;DSN=Personel;UID=mustafa;" & _
"PWD=mmtt12;DATABASE=Personel"
Set db = OpenDatabase(App.Path & "\Personel.mdb")
db.Execute "DELETE FROM bPers WHERE dyer = ' Ankara'"
db.Close
4.4.2. ODBC VERİLERİNE ODBCDIRECT KULLANARAK ERİŞİM
ODBCDirect kullanmak için önce bir ODBC Workspace yaratmak gerekir. Bu CreateWorkSpace metodu kullanılarak yapılabilir. Bu işlem aşağıdaki gibi yapılabilir.
Dim wks As Workspace
Set wks = DBEngine.CreateWorkspace("ODBCWks", "mustafa", "mmtt12", _
dbUseODBC)
ODBC Workspace yaratıldıktan sonra yapılması gereken ODBC veri kaynağıyla bağlantı kurmaktır. Bağlantı OpenDatabase metodu ile yapılır. Parametre olarak uygun bir bağlantı metni verilir. Veri kaynağına bağlanmak için iki yol vardır. Bunlar Database nesnesi yaratmak ve Connection nesnesi yaratmaktır. Connection nesnesi ODBC verilerine erişimde sağladığı bazı olanaklar sayesinde verimlilik sağlar. Bu olanaklar;
Bu olanaklardan yararlanmak için kullanılan Connection nesnesi aşağıdaki gibi kullanılır.
Set variable = workspace.OpenConnection (dsName, prompt, readonly, connect)
Bu metodun kullanışı şu şekilde örneklenebilir.
Dim cnn As Connection, strCn as String
strCn = "ODBC;dsn=Pubs;database=Pubs;uid=sa;pwd=;"
Set cnn = OpenConnection("", dbDriverNoPrompt, False, strCn)
Connection nesnesi yaratıldıktan sonra bu nesne üzerinde Recordset yapısı tanımlamak ve üzerinde sorgu yapmak mümkündür.
ODBCDirect yöntemiyle aynı ODBC veri kaynağı üzerinde hem Connection hem de Database nesnesi tanımlamak mümkündür. Database nesnesi ancak Microsoft Jet veritabanı motorundan yararlanılacaksa kullanılmalıdır.
4.5. VERİTABANI PERFORMANSINI ENİYİLEŞTİRME
Yerel ve uzak veritabanı sistemleri arasında önemli farklar olduğundan dolayı performansları da farklıdır. Yanlış tasarlanmış bir Client/Server veritabanı ihtiyaçlara cevap vermez. Bu sebepten dolayı client/server yapısında veritabanı tasarlanırken çok dikkatli olunmalıdır.
Sorguların hızlandırılması
Uzak bir sistemdeki sorguların performansını artırmak için yapılabilecek en iyi şey sorguların olabildiğince fazla kısmını sunucu üzerinde çalıştırmayı sağlamaktır.
Microsoft Jet veritabanı motoru verilen bir sorgu için ön işlemleri yaparak bunu ODBC veri kaynağının desteklediği türden sorgular haline getirir. Eğer bir sorgu bir çok deyim içeriyorsa bir ön işlemeye ihtiyaç vardır. Bu ön işleme yerel olarak yapılır. Sorguları iyileştirmek için sorgularda genel olarak sağlanan işlevler kullanılmalıdır.
Genel olarak sağlanmayan işlevler şunlardır.
Eğer işlem sunucu tarafından destekleniyorsa, doğrudan sunucuya gönderilir, desteklenmiyorsa yerel olarak işlenir.
Daha az veri istemek
Ne kadar çok veri istenirse ağ trafiği o kadar artacağından erişim hızı gittikçe düşer. Artan ağ trafiği sunucunun işlem yükünü de artırır. Bu istenmeyen durumlara engel olmak için;
Alanları sadece istendiğinde gösterme
Form içinde veritabanı tablosunun alanları gösterilirken bazen sadec bir alanın tüm değerleri kullanılırken, bazen de bir tutanağın tüm alanlarına ihtiyaç duyulur. Bu tür durumları ele almak için şu yöntemler kullanılabilir.
Verileri birden fazla form için kullanılmak üzere istemek
Genellikle uygulamalar, birden fazla form kullanır ve bu formlar uzak sistemlerdeki aynı verilere erişir. Bu tür durumlarda performans iyileştirmek için şunlar yapılabilir.
İşlevselliği daha az kullanma
Veritabanının performansının iyileştirilmesi için, Microsoft Jet veritabanı motoru tarafından sağlanan bazı işlevlerin kullanılmasından sakınmak gerekir.
Uzak verilerin geçici Recordset yapılarında tutulması
Gunleme ve silme işlemleri için performansını artırmanın en basit yolu, uzaktaki tabloya tablonun ne zaman değiştiğini belirten bir alan yerleştirmektir. Bu alan sunucu tarafından yönetilir ve tutanak günlendiği anda günlenir. Bu alanı doğrudan okumak mümkün olmasa bileMicrosoft Jet bu alan sayesinde tutanağın değişip değişmediğini algılayabilir. Böyle bir alanın olmadığı durumlarda bir tutanağın değişip değişmediğini anlamak için tüm tutanağın karşılaştırılması gerekir. Bir tabloya böyle bir alan aşağıdaki SQL deyimiyle eklenebilir.
ALTER TABLE UzakTablo ADD SonDegZ TIMESTAMP
Bu deyimle UzakTablo adlı tabloya SonDegZ adlı, tablonun son değiştiği zamanı belirten bir alan eklenir.
Uygulama performansını artırmanın bir diğer yolu da uzaktaki veriyi geçici bellek alanlarında tutmaktır.
Bir Recordset tanımlayıp bunu yerel
bilgisayara kopyalamak için Recordset yapısının CacheStart, CacheSize özellikleri ve
FillCache metodu kullanılabilir. Verilerin bir kopyasını yerel bilgisayara almak bu
Recordset yapısı üzerinde yapılacak sorguların hızını artırır.