Mega Code Archive

 
Categories / Delphi / Strings
 

Interbase zaafları ve vtys sistemleri hakkında söyleşi [2]

Otomatik Sayı sorunu, tetikleyicinin birincil anahtarlarla uyumsuz olması. - Tablolar oluşturulurken birbirlerini lego gibi tamamlar nitelikte tasarlanırlar. Örneğin müşteriyi her seferinde ismini ve bilgilerini girmek yerine ayrı bir tablodan referans numarası verilerek ihtiyaç duyulduğunda bu referans numarasıyla çağrılması tüm tasarlanan tablo yapılarında vardır. Otomatik sayı alanlarının değerini veritabanları otomatik olarak verirler. Bazı veritabanı sistemleri bunun için Autoincrement (otomatik artan sayı) alanı kullanırlar. Fakat bu interbase içerinde alan türü olarak yer almamaktadır. En çok ihtiyaç duyulan alan türlerinden birisi Boolean, 7.x sürümünden sonra eklenmiştir. Otomatik artan sayı alanları için tetikleyici yazmanız gerekmektedir. Örneğin aşağıdaki gibi: URUN_NO=GEN_ID(URUN_NO,1); Bunu yaptığınızda ihtiyacınızı görecektir fakat birincil anahtar oluşturduğunuzda, çakışma yarattığını göreceksiniz. İsterseniz böyle bir tablo oluşturup birincil anahtar alanları olan ve otomatik artan sayı alanı için bir tetikleyiciye sahip olan örnek tablo tasarlayın. Delphi içinden kayıt işlemi yapmak istediğinizde ekrana hata mesajı belirecek işlem başarısız olacaktır. Bu sorunu aşmak için çözüm yöntemi; otomatik artan sayı alanı için tetikleyici yazmak yerine depolanmış yordam ile yapmaktır. Böylece hiçbir çakışma yaşanmayacaktır. Depolanmış yordam kayıt eklendiğinde otomatik çalıştırılmaz çünkü tablodan bağımsızdır. Bunun için Datasetin AfterInsert() olayının içerisine IBStoredProc bileşeniyle çalıştırmaktır. Tabii bu işlemleri yaparken üretecin (generator) daha önceden oluşturulmuş olması gerekir. Depolanmış yordam geriye çıkış değeri gönderecektir. Bu sayı değerini kod yordamıyla tablodaki alana aktarmanız gerekir. Örnek olarak: -------------------------------------- "Urun_No" (Double Precision) Not Null, "Urun_Adı" (Char(20)), Primary Key ("Urun_No") -------------------------------------- Alanları bulunan ve "urunno" isimli bir üretecin var olduğunu düşünerekten anlatılanları yorumlayabilirsiniz. Sunucu üzerinde ilgili işlemleri yaptığınızda sorun yaşanacaktır. Bunun için yukarıdaki yönergeyi dikkate almanızda fayda var. Depolanmış yordam ise şu şekilde olacaktır. Yani tetikleyiciye yazacağımız kodu buraya yazıyoruz: -------------------------------------- CREATE PROCEDURE "otomatik_sayi_uret" RETURNS ( "URUN_NO" DOUBLE PRECISION ) AS BEGIN URUN_NO=GEN_ID(URUN_NO,1); END; -------------------------------------- Delphi içerisinde dataset (IBQuery,IBtable v.b.) içerisinde AfterInsert() olayına aşağıdaki kodu uyarlayınız: -------------------------------------- procedure TForm1.IBTable1AfterInsert(DataSet: TDataSet); begin IBStoredProc1.Prepare; try IBStoredProc1.ExecProc; IBTable1.FieldByName('URUN_NO')Value := IBStoredProc1.ParamByName('URUN_NO').Value; finally IBStoredProc1.UnPrepare; end; end; -------------------------------------- Yeni kayıt eklenip kaydedildiğinde otomatik sayı alan değerinin istemciye yansımaması. - Interbase IBX bileşenlerinden dataset sınıfının en büyük zaafı kayıt saklandığında çalışan tetikleyiciden dönen değerin istemciye gönderilmemesi. Örnek olarak yukarıdaki tablo yapısında ve bir adet tetikleyici ile otomatik sayı değerinin verildiği bir tabloyu "IBTable" bileşeni ile bağlanmayı deneyin. Yeni bir kayıt ekleyin ve ürün adı alanını doldurun, ardından kaydedin. Dikkatle baktığınızda bu alan değerini okuyamayacaksınız ve değer kısmının boş olduğunu göreceksiniz. Fakat sunucuda bu değer verilmiştir. Ancak yenile (refresh), veya ekleme (insert) metotları uygulandığınızda, yeni bir işleme geçildiğinden referans alanındaki sayı değerini okuyabilirsiniz. Ayrıca ekrandaki kayıt sırası kaybolarak ilk kayda gidilecektir. Bu işlem ise milyonlarca hatta yüzlerce kayıt bulunan bir tabloda ne kadar kod yazsanız da 7-8 saniyelik sinir bozucu bekleme sürelerine yol açar. Kaydın referans alanında bulunan değer alt tablolarda saklanmak istendiğinde null bir alan gibi görünen ama sunucuda var olan değere ulaşamayıp gereksiz kodlamalara yol açacaktır. Borland, bu hata ile ilgili bir çözüm hala üretmedi. Ama yukarıdaki yöntemi kullanarak bu sorunun üstesinden gelebilirsiniz. IBDataSet bileşenin GeneratorField özeliğini kullanarak da bu işi yapabilirsiniz. Ayrıca tetikleyici yazmanıza da gerek kalmayacaktır. Fakat çok değil kayıt sayısı bin değerine ulaşmadan işlemlerin yavaşlamaya başladığını fark edeceksiniz. Bunun sebebi dataset her hareketi yaparken içerisindeki SQL sorgusunu çalıştırması. İlişkili tablolarda gözle görülür derecede yavaşlama olur. Hele ki bir dataset bileşeninde gözat (lookup) alanları ortalama 5 in üzerinde ise bu can sıkıcı yavaşlamalara yol açıyor. Yavaş bilgisayarlarda çalışıyorsanız bu çok fazla göze çarpar. Hatalı tarih biçimi - Diğer karşılaştığımız bir hata ise interbase konsol programının verileri ihraç komutu verdiğinizde (extract table data - tablo özelliklerinden baktığınızda alttaki onay kutusu) tarih alanlarının sistemde tanımlı olan tarih biçiminde değil de, amerikan tarih biçiminde verildiğini göreceksiniz. İşin ilginç tarafı aynı verileri tekrar eklemek istediğinizde bu sefer sistem tarih biçimini temel alarak tarih biçimini uygun bulmaması ve hata üretmesi .. Hesaplanabilir alanlar - Interbase, tabloları içerisinde hesaplanabilir alanlar (delphi deki calculated gibi) oluşturulmasına imkan verir. Bunu computed by deyimiyle alan isminden sonra tanımlayabilirsiniz. Fakat bu delphi içerisindeki hesaplanabilir alanlar gibi etkileşimli çalışmaz. Yani düzenleme, ekleme vb. gibi işlemlerde, alan değeri gösterilmez. Ancak gezinti modundayken bu alanların hesaplanarak, sunucudan istemci programa gönderildiğini göreceksiniz. Tablolarınızı tasarlarken bu durumu göze almanızda fayda var. Programı hazırlamaya başladıktan sonra fark etmeniz sizin için yapıyı tekrar tasarlamanız konusunda zaman kaybına yol açabilir.