Konu: Visual Foxproda index kırılması
Visual Foxproda oluşan index kırılmalarına karşı ne gibi önlemler alınabilir. Uzman arkadaşlarımızın bu konudaki önerilerini bekliyorum. İlginiz için şimdiden teşekkür ederim.
Giriş yapmadınız. Lütfen giriş yapın yada kayıt olun.
Visual Foxproda oluşan index kırılmalarına karşı ne gibi önlemler alınabilir. Uzman arkadaşlarımızın bu konudaki önerilerini bekliyorum. İlginiz için şimdiden teşekkür ederim.
bence en iyisi PACK veya REINDEX komutu ile belli zaman aralıklarında düzenlemek
aşağıdakini örneğin aydabir geceyarısı çalıştır. (kodu doğaçlama kontrolsüz yazdım)
=ADIR(fa,"c:\dosyaklasörü\*.dbf")
FOR Xi=1 TO ALEN(fa,1)
WAIT fa[Xi,1] NOWAIT WINDOW
m.hFile = FOPEN(fa[Xi,1], 12)
IF (m.hFile > 0) && Not used
FCLOSE(m.hFile)
USE (fa[Xi,1]) EXCL
PACK && REINDEX
USE
ENDI
ENDF
"kırılmak == bozulmak" anlama geliyorsa:
Ben kendim için bu sorunu şöyle çözdüm:
1. Uzun süredir artık FoxPro'nun kendi veritabanını kullanmiyorum.
2. Eski yazdığım programlarda:
- Dosyayalarımı sadece kullanacağım vakit açıyorum, sonra hemen kapatıyorum
- Programın servis modülünde "dosya bakım" diye bir seçenek var: tabloların tüm index'lerini siliyor, tabloya "PACK" komutunu uyguluyor ve sonra tekrar tüm index'leri yaratıyor. Bir müşteri beni aradığında, ilk sorum "dosya bakım yaptınızmı?" oluyor. Ekseri yapmamış oluyorlar, ve yaptıkdan sonra ekseri cevap olarak "Aaaa, düzeldi!" duyuyorum.
-Kesintisiz guc kaynagi
-Dosyalarin mumkun oldugu kadar az acik tutulmasi.
En saglami da VFP yerine SQL server gibi bir database kullanmak:)
üstadlara ek olarak, naçizane birkaç ekleme:
- tabloları kapatırken Windows'un buffer'daki datayı yazarak boşaltmasını sağlamak için;
FLUSH IN (tablom) FORCE
USE IN (SELECT(tablom))
- bir tabloyu sadece data almak için açacaksam, onu read-only yapıyorum
USE tablom NOUPDATE
konu acilmisken benden de bir soru;
network ortaminda calisan cok kullanci bir yazilimim var. buffer 5 kullaniyorum actigim dosyalarda. yeni fis actigimda fisler karismasin diye once dosyayi kilitleyip sonra fis numarasi alip hemen tableupdate yapiyorum. buna ragmen fislerde karisma oluyor. yani ayni anda birlikte fis acan iki kullanicinin zaman zaman fis satirlari karisiyor. nedeni sizce nedir ? bir oneriniz var mi?
Öncelikle ESAS fiş numarasını kaydetmeden önce kesinleştirme,
işlemler sırasında geçici bir fiş numarasını
SYS(2015) && veya illa numerik istiyorsan
CHRT(SYS(2015),'_ABCDEFGHIJKLMNOPQRSTUVWXYZ','123456789012345678901234567')
benzeri metod ile yaratıp, kaydı yukardaki unique numara ile tamamlayıp, sonraki komut satırında esas fiş no ile değiştirebilirsin --- veya ----
kayıt sırasında kaydı yeni fiş no ile yapılabilinir (INSERT INTO (APPE BLAN değil) )
(muhtemelen çakışma milisaniyeden az sürece kalır)
--- başka aklıma gelen ---
VFP yeni kayıtta yeni RECNO() yu - değer olarak kullanıyor, kesinleştiği noktada + yaparak kaydı tamamlıyor.
benzeri algoritma da geliştirebilirsin
---
TABLEUPDATE - FLUSH benzeri fonksiyonlarla hep kötü tecrübem oldu.
Yeni esas fiş numarası alırken nasıl yaptığını bilmiyorum:
SELECT MAX(yenifişno) AS yfn FROM fişdosya INTO CURS curYenifiş
m.yenifişno=NVL(curYenifiş.yfn,0)+1
INSERT INTO fişdosya (fişno, ...) VALUES (m.yenifişno, ...)
benzeri kodla daha olumsuz tecrübem olmadı
konu acilmisken benden de bir soru;
network ortaminda calisan cok kullanci bir yazilimim var. buffer 5 kullaniyorum actigim dosyalarda. yeni fis actigimda fisler karismasin diye once dosyayi kilitleyip sonra fis numarasi alip hemen tableupdate yapiyorum. buna ragmen fislerde karisma oluyor. yani ayni anda birlikte fis acan iki kullanicinin zaman zaman fis satirlari karisiyor. nedeni sizce nedir ? bir oneriniz var mi?
Ben numaralar icin tamamen ayri bir tablo tutuyorum.
IDS: tableName c(50), nextID i - index on upper(tablename) tag tableName
Kod'da soyle (stored procedure)
Function NewID
Lparameters tcAlias,tnCount
Local lcAlias, lnOldArea, lcOldReprocess, lcTable, lnTagNo, lnNewValue, lnLastValue, lcOldSetDeleted
lnOldArea = Select()
lnOldReprocess = Set('REPROCESS')
* Uppercase Alias name
lcAlias = Upper(Iif(Parameters() = 0, Alias(), tcAlias))
* Lock reprocess - try once
Set Reprocess To 1
If !Used("IDS")
Use ids In 0
Endif
* If no entry yet create
If !Seek(lcAlias, "Ids", "tablename")
Insert Into ids (tablename, NextID) Values (lcAlias,0)
Endif
* Lock, increment id, unlock, return nextid value
Do While !Rlock('ids')
* Delay before next lock trial
lnStart = Seconds()
Do While Seconds()-lnStart < 0.01
Enddo
Enddo
lnLastValue = ids.NextID
lnNewValue = m.lnLastValue + Evl(m.tnCount,1)
*Try to query primary key tag for lcAlias
lcTable = Iif( Used(lcAlias),Dbf(lcAlias), Iif(File(lcAlias+'.dbf'),lcAlias,''))
lcTable = Evl(m.lcTable,m.lcAlias)
If !Empty(lcTable)
Use (lcTable) In 0 Again Alias '_GetPKKey_'
For m.lnTagNo=1 To Tagcount('','_GetPKKey_')
If Primary(m.lnTagNo,'_GetPKKey_')
m.lcOldSetDeleted = Set("Deleted")
Set Deleted Off
Select '_GetPKKey_'
Set Order To Tag (Tag(m.lnTagNo,'_GetPKKey_')) ;
In '_GetPKKey_' Descending
Locate
lnLastValue = Max(m.lnLastValue, Evaluate(Key(m.lnTagNo,'_GetPKKey_')))
lnNewValue = m.lnLastValue + Evl(m.tnCount,1)
If Upper(m.lcOldSetDeleted) == 'ON'
Set Deleted On
Endif
Exit
Endif
Endfor
Use In '_GetPKKey_'
Select ids
Endif
* Increment
Replace ids.NextID With m.lnNewValue In 'ids'
Unlock In 'ids'
Select (lnOldArea)
Set Reprocess To lnOldReprocess
Return ids.NextID
Endfunc
Bunu database'ine SP olarak ekledikten sonra ornek kodlar:
open database dbName
lnID = NewID("Musteriler") && musteriler icin 1 ID al
lnID = NewID("Musteriler", 10) && musteriler icin blok 10 ID al - gelen kullanacagin son numara. 88 geldiyse 88-10+1 ilk. 79-88 senin
Tablolarda ID alanin icin default deger:
NewID("TabloAdi")
Bu da SQL/VFP OLEDB icin getNextID (oApp custom nesne, o sirada kullanilan db icin connectionstring tutuyor):
Lparameters tcTableName, tnCount
IF VARTYPE(oApp)!='O' AND VARTYPE(_screen.oApp) = 'O'
oApp = _screen.oApp
endif
Local loConn as 'ADODB.Connection',loCommand as 'ADODb.Command',loRS as 'ADODb.RecordSet',lnReturn
loConn = Createobject('ADODB.Connection')
loCommand = Createobject('ADODB.Command')
loConn.ConnectionString = oApp.ADODataConnectionString
loConn.Open
loCommand.ActiveConnection = loConn
loCommand.CommandType = 4 && stored procedure
Do Case
Case oApp.DataMode == 'SQL'
loCommand.CommandText = 'NextID'
loCommand.Parameters.Refresh
loCommand.Parameters('@tableName').Value = m.tcTableName
loCommand.Parameters('@nRows').Value = EVL(m.tnCount,1)
loCommand.Execute
lnReturn = loCommand.Parameters('@end').Value
Case oApp.DataMode == 'VFP'
loCommand.CommandText = Textmerge('NewID("<<m.tcTableName>>",<<EVL(m.tnCount,1)>>)')
loRS = loCommand.Execute
lnReturn = loRS.Fields(0).Value
loRS.Close
Endcase
loConn.Close
Return m.lnReturn
Dikkat edersen lock sadece ilgili record'da RLock(). Lock icin yarismayi onlemek icin reprocess 1 ve arada beklemeler var. Sorunsuz calisiyor yillardir, cok sayida musteride.
Not: Tabii gonlum yine de GUID'den yana hic boyle dertleri yok. Yenilerde NOSQL veri tabanlariyla ilgileniyorum, orada ID'ler hep GUID tarzi ve cok cok hizlilar (Ilgilenme 'oynama' safhasinda ve .Net ile. VFP icin zaten cogunun hic destegi yok). Simdilik hizlari, kolayliklari karsisinda agzim sulaniyor o kadar.
konu acilmisken benden de bir soru;
network ortaminda calisan cok kullanci bir yazilimim var. buffer 5 kullaniyorum actigim dosyalarda. yeni fis actigimda fisler karismasin diye once dosyayi kilitleyip sonra fis numarasi alip hemen tableupdate yapiyorum. buna ragmen fislerde karisma oluyor. yani ayni anda birlikte fis acan iki kullanicinin zaman zaman fis satirlari karisiyor. nedeni sizce nedir ? bir oneriniz var mi?
örnegin table'de FISNO adında bir indexli field var buda 1,2,3,4,5,... diye digiyor
kullanıcı fişi kaydettiği anda
set orde to fisno
go botto
yeniID=fisno+1 şeklinde ID elde ediyorum
vede yeni fiş noyu yeni ID kullanrak kaydedıyorum.
Bunla ilgili hiç sıkıntı yaşamadım.Sadece index kırılması hariç tabiki
Bu yöntem basit gibi görünüyor ama eksiği varmı sizce?
Ben Cetin hocamin yontemini kullaniyorum IDS.dbf ister DE de ister load ta use ile acilsin buffermode a dahil edilmiyor /ben etmiyorum / yani yeni islemno,ftno vs ne isterseniz isteyin siradakini getiriyor arada bosluklar( takip eden numaralar) olabilir ama cakisma kesinlikle olmuyor...Yani hep garanti ve siradaki numara aliniyor...