1

Konu: use ile açılan dosyaları kapatmak

fox pro üsdatları, bir konuda görüşlerinizi almak istiyorum,kullanmak istediğim dosyaları ihtiyacım olduğu andamı açmalıyım,yoksa forma girişte kullanacağım tüm dosyaları açmam mı gerekir?Hız ve performans açısından soruyorum bu soruyu,bir de diyelimki 10 adet table use ile açtıktan sonra dosyaları kapatmadan formdan çıktığımızda programın çalışma hızı etkilenirmi?problemim her zamanki gibi hız arkadaşlar,Görüşlerinizi bekliyorum.:)

En büyük sermaye nakit,nakit sermaye vakittir...

2

Re: use ile açılan dosyaları kapatmak

1) Formalrinda private datasession kullan
2) Gerektiginde orada acilsin, cikarken kapanir
3) Buffering kullan

Senin sorun hiza yonelik. Hiz sadece buna bagli degil, datanin native ya da SQL server olmasi filan da isin icinde. O nedenle yukaridakiler mutlak kurallar degil. VFP native icin pratik kurallar ve hiz zaten farkedemeyecegin kadar az farkeder. Dosyayi bozulmaktan koruma on planda.

3

Re: use ile açılan dosyaları kapatmak

dosyayı bozulmaktan korumak için
sürekli açık olması mı daha mantıklı  yoksa gerektiği anda açıp kapatmak mı  ?

teşekkürler

4

Re: use ile açılan dosyaları kapatmak

Ne kadar kapali olurlarsa o kadar iyi:) Ama acik olmalari da bozulmaya neden olan sey omadigina gore acik kalmasi da performans acisindan onemli. Bozulma anlari yazma zamanlarinda. Hic yazmiyorsan hep acik kalsa da olur.

5

Re: use ile açılan dosyaları kapatmak

çetin üsdadım  formun data  datasession özelliğinin  "private datasession "  ile "default data datasession" olmasının teknik açıdan farkı nedir? "private datasession " u bir formumda uyguladığımda foxpro dosya yazma işleminde sürekli onaylama mesajı gösteriyor,bunu nasıl engellerim?(daha önce aynı formda listelelen  kayıtları excele gönderdiğimde direk işlemi yapıyordu,private datasession kullandığımda, sürekli, bu excel tablosu var üzerine yazmak istediğinizden emin misiniz gibi bir mesaj çıkıyor. )

En büyük sermaye nakit,nakit sermaye vakittir...

6 Son düzenleyen, ercan (21.07.2007 15:07:17)

Re: use ile açılan dosyaları kapatmak

SET SAFETY OFF          yap düzelir (doğrusu safety , her zaman karıştırırım set safety  ile set  confirm mi) smile sağol çetin hocam

7

Re: use ile açılan dosyaları kapatmak

ercan üsdat SET CONFIRM OFF    yaptım ama  değişen hiç bir şey olmadı.

En büyük sermaye nakit,nakit sermaye vakittir...

8 Son düzenleyen, cetinbasoz (21.07.2007 11:52:07)

Re: use ile açılan dosyaları kapatmak

Neyzen,
Onun private datasession olmasiyla ilgisi yok. Yalniz private datasession kullandiginda dikkat etmen gereken, bircok SET komutu session'a ozel, yani bir yerde SET TALK ON iken digerinde OFF olabilir. Bir kere kurdum tamam diye dusunme. Senin dedigin SET SAFETY OFF. Bu arada benim formun load'inda cagirdigim setups.prg:

SET EXCLUSIVE OFF
SET DELETED ON     && No need to see records marked for deletion
SET ESCAPE OFF     && Do not allow intruption of the program
SET REPROCESS TO 1
SET TALK OFF
SET CENTURY on
SET CENTURY TO 19 ROLLOVER 60
SET SECONDS OFF
SET DEBUG OFF
SET HOURS TO 12
set multilocks on
Set Nulldisplay To ""
Set Safety off

Hepsi session'a ozel degil ya neyse yazmisim kalmis:)

9

Re: use ile açılan dosyaları kapatmak

çetin hocam  "private datasession "  ile "default data datasession" arasındaki farkada bir değinebilirmiyiz :-)

En büyük sermaye nakit,nakit sermaye vakittir...

10

Re: use ile açılan dosyaları kapatmak

Data Session'i senin tablolarinin, cursorlerinin acildigi calisma masasi gibi dusun. Ikimizde ayni sirkette, ayni odada calisiyoruz (oda VFP'nin kendisi olsun).
Ikimizin de calisma masalari var. Benim masama actigim evraklar ve senin kendi masana actigin evraklar var. Tesadufen ilimiz de, evrak arsivinden aldigimiz, musteriler dosyasi ile calisiyoruz (gercek hayatta ya sen ya ben aliriz burada birer kopyesini aldik diyelim). Benim actigim sayfa X, seninki Y. Benim Z'ye gecmem seni etkilemiyor, sen hala Y ile calisiyorsun. Ben Z'yi degistirsem ve kaydetsem (tableupdate, commit ya da hic buffer yok) senin sihirli evrak yonetimi sayesinde, Z'ye bakarsan o degisiklik orada. Sen tum dosyalarini kapatsan ve toplayip evrak arsivine teslim etsen de ben calismaya devam edebiliyorum. Uzun lafin kisasi masalarimiz bagimsiz. Bu private data session gibi.

Default data session arsivin kendisi gibi ya da masalarimizdan birisi (VFP acildiginda aktif olan data session 1, global data session, o her zaman var). Eger ikimiz de orada calissaydik (biz ornegin Form'uz) illa ki ayni anda X'e, Y'e. Z'e vs bakmamiz gerekecekti. Ben kapatirsam butun dosyalari senin icin de kapanmis olacakti (senin haberin olmadan kapttigimi dusun Y'nin adi ne diye bakmaya kaltiginda veya Z'ye sunu yaz dedigin anda ortada dosya yok yazacak).

Default ile Global'i karistirma. Global data session daima datasessionId = 1 olan VFP acildigindaki session. Default biraz farkli ondan, soyle ki eger ben private datasessionda isem ve onun IDsi 4 ise, burada acilan default data session ayni session'i yani 4'u kullanir. Biraz karisik oldu galiba:

*Form calisiyor - private datasession. DataSessionID = 4
-Bir buton ile modal form aciyorum (ya da nonModal)
-Acilan yeni form private degil default kullaniyor. O zaman, acildigi session onun session'i yani 4 Id'li. Dataenvironment'inda AutoCloseTables var ve benim onceki formda kullandigim tablolardan birisi o dataenvironmentda mevcut ise, donuste onu kapatir ve benim gariban formumun bundan haberi yoksa vay haline. Ya da daha vahimi o cagirdigim form  donuste "close tables all" derse cagiran form yandi.

Bir baska benzetme ile, private session ayni VFP icinde calisan bircok bagimsiz data kutucuklari gibi (data slots). Ama ne kutucuk, her birinde 32767 dosya acabiliyorsun (toplamda 65535 file handle'i gecemedigini varsayarsak), istediginde istedigin gibi dolas, diger kutucuklarda acilanlar ile ilgin yok.
Tek bir makine, tek bir VFP uygulamasinin icinde multiuser gibi (nerdeyse).

Private Datasession benim bakis acimdan foxpro2x'ten sonra VFP ile gelen bir nimet:)

Data sessionlar arasinda bir bariyer var, bunu bilmen gerekiyor. Bir session'in tablosuna baska bir sessiondan dokunamazsin ancak tablo diskte olduguna gore sende acar istedigini yaparsin. Cursor ise diskte karsiligi olasa da olmasa da tamamen yaratana ozel olduguna sessionlar arasinda hicbir sekilde gecemez. Simdi yanlis anlamalari onlemek ve kendimi yalanci durumuna durumemek icin biraz ornekleyeyim (tabii bu arada ihtiyacin olursa ne yapabilirsin) - tum formlarda private session oldugunu varsayalim:

-Form1

Visual Fox Pro
use customer

locate for cust_id = "ANATR"
select * from customer where country = 'USA' into cursor crsWork nofilter

-Form2

* Form1'de hangi customer secili bilmek istiyor. oForm, form1'in referansi olsun
? customer.cust_id && form1 session'a ulasmiyor. 2 sonuc olabilir.

* 1) Burada customer acilmamissa alias not found - ozel bir durum var hata almayacagin ama konu disi
* 2) Burada customer aciksa, kendisinde o sirada hangi kayitta ise o. Herkesin kendi masasi:)

Form1'inkini almakta israr ediyor. Alamaz mi? Alir. DataSession'larin IDsi var.

set datasession to oForm1.DataSessionId
lcID = customer.cust_id && sadece PKyi sordu
set datasession to thisform.dataSessionID

Gecisi olarak datasession degisitirip o hangisinde bakti, dondu.

Simdi gelelim form1 deki crsWork'e. Ona datasessionId degisitirip bakabilir, browse edebilir vs. Ancak butun bu islemleri bariyaerin karsi tarafinda yapiyor olur. O Country='USA' olanlari secti, ben o settekilerin ordelarini almak istiyorum:

set datasession to oForm1.DataSessionId
select * from Orders where cust_ID in (select cust_id from crsWork) into cursor crsSiparis nofilter
browse && vs gecerli - ancak crsSiparis artik bariyerin o tarafinda, o form icin var
set datasession to thisform.dataSessionID
select crsSiparis && ooops. crsSiparis yok burada
* Ya da bu gecersiz - bu session crsWork'ten habersiz
select * from Orders where cust_ID in (select cust_id from crsWork) into cursor crsSiparis nofilter

Ne yazik ki, bu session icinde ayni islemi yapmasi lazim burada da istiyorsa onlari:

select * from customer where country = 'USA' into cursor crsWork nofilter
select * from Orders where cust_ID in (select cust_id from crsWork) into cursor crsSiparis nofilter

gibi. Sinirlar cok iyi korunuyor yani:) Datasession bariyerlerini "hic bir cursor gecemez". Peki cursorlar gecemezse ve:

select * from customer where country = 'USA' into cursor crsWork nofilter

milyonlarca kayittan yapilmis ya da SQL server vs'den gelmis, elde etmesi pahali ve zaman alan bir islem ise ne olacak (sonuc ise topu topu birkac yuz veya birkac bin record olsun)? Bircok formda da ihtiyacin var. Cevabi tartismali. Default datasessionda yap, onu kullanacaklar default datasession kullansin diyenler var, ona katilmayanlar da (ben katilmiyorum). Onun yerine bu bariyerleri nasil geceriz:

-Cursor gecemez. Ama tablolar diskte, session problemi yok.
select * from customer where country = 'USA' into table crsWork nofilter
use && kapatilana kadar exclusive kullaniyor

olabilirdi. O zaman butun sessionlar buna ulasir (use, select...). Bunun yaratacagi problem ortada runtime'da ayni anda birden fazla yer bu tabloyu yaratmaya kalkar vs.

-Viewler cozum degil. Cunku view SQL'in tanimi iceriyor. Select yapmakla ayni sey zaman alir.

-O bariyerleden sadece cursorlar gecemiyor, degiskenler gecer:) O zaman o tablonun icerigini bir degiskene alabiliriz:

Visual Fox Pro
select * from customer where country = 'USA' into table crsWork nofilter

loData = createobject('Empty') && vfp3,5,... ise custom,line filan ile oluyor. kod biraz farkli
addproperty(loData, "RecordCount", reccount('crsWork') )
addproperty(loData, "aRecord[' + transform( reccount('crsWork') ) + ']')
scan
  scatter name loData.aRecord[recno()] memo
endscan

Tepe tepe kullanilmaya, datasessionlar arasinda dolasmaya hazir bir objemiz var:) Yukaridaki yaklasimi daha iyi gosteren hazir bir classim var. Onunla ornek gostereyim ve bitsin (private sessionli formlari taklit etmek icin private session kullanan 'session' objeleri var. Olayin nasil dondugunu anlamak icin bunu denerken Window\Data session ac. 3 farkli yerde farkli tablolar var - default(1)'de acilan hcbirsey yok - DataSessionPass.prg adiyla saklayip denemezsen biriki yerde ufak degisikilik yapman gerekli, NewObject()lere bak):

Visual Fox Pro
* DatasessionPass.prg

Local loSession1, loSession2
* Create 1st private datasession
loSession1 = Createobject('Session1')
loSession1.SomeQueries() && run some queries
 
loSession2 = Createobject('Session2')
loSession2.GetTheDataAndBrowse(loSession1) && transfer data from session1
 
 
Define Class session1 As Session
  DataSession = 2 && Private
 
  Procedure SomeQueries
 
    Select * From (_samples+'data\customer') Where country = 'USA' Into Cursor crsUSA
    Select ord.* From (_samples+'data\orders') ord ;
      INNER Join crsUSA On crsUSA.cust_id == ord.cust_id ;
      ORDER By ord.cust_id, ord.order_date ;
      INTO Cursor crsUSAOrders ;
      nofilter
 
  Endproc
 
  Procedure GetDataCursors( tcAliasList, tcAsAliasList )
 
    If Empty(m.tcAsAliasList)
      tcAsAliasList = m.tcAliasList
    Endif
 
    Local laAlias[1], laAsAlias[1]
    Local oDataSetPacker As 'DataSet' Of Fullpath('DatasessionPass.prg')
    Local ix, lcAlias, lcAsAlias
    oDataSetPacker = Newobject('DataSet',Fullpath('DatasessionPass.prg'))
 
 
    Alines(laAsAlias, m.tcAsAliasList,1,',')
    For ix = 1 To Alines(laAlias, m.tcAliasList,1,',')
      lcAlias   = laAlias[m.ix]
      lcAsAlias = Iif(m.ix > Alen( laAsAlias ), laAlias[m.ix], laAsAlias[m.ix] )
      oDataSetPacker.AddTable(m.lcAlias, m.lcAsAlias)
    Endfor
    Return oDataSetPacker
  Endproc
 
Enddefine
 
Define Class session2 As Session
  DataSession = 2 && Private
 
  Procedure GetTheDataAndBrowse(toOtherSession)
    Local loDataSet
    loDataSet = toOtherSession.GetDataCursors( ;
      'crsUSA, crsUSAOrders', 'crsCustomer,crsOrders' )
    loDataSet.RestoreDataset(This.DataSessionId)
    Select crsCustomer
    Browse
    Select crsOrders
    Browse
  Endproc
 
Enddefine
 
 
** Dataset class to pack given cursors into an object to pass between data sessions
Define Class DataSet As Custom
  TableCount = 0
  DataSessionId = 0
  Dimension TableInfo[1]
 
  Procedure Init
    This.DataSessionId = Set("Datasession")
  Endproc
 
  Procedure AddTable(tcAlias, tcAsAlias)
    Local Array aStruc[1],aStripped[1]
    Afields(aStruc,m.tcAlias)
    Dimension aStripped[ALEN(aStruc,1),5]
    For ix = 1 To Alen(aStruc,1)
      aStripped[m.ix,1] = aStruc[m.ix,1]
      aStripped[m.ix,2] = aStruc[m.ix,2]
      aStripped[m.ix,3] = aStruc[m.ix,3]
      aStripped[m.ix,4] = aStruc[m.ix,4]
      aStripped[m.ix,5] = aStruc[m.ix,5]
    Endfor
    This.TableCount = This.TableCount + 1
    Dimension This.TableInfo[this.TableCount]
    This.TableInfo[this.TableCount] = Createobject('Custom')
    With This.TableInfo[this.TableCount]
      .AddProperty('aStructure[1]')
      .AddProperty('aRecords[1]')
      .AddProperty('Records')
      .AddProperty('Alias',m.tcAlias)
      .AddProperty('AsAlias', Iif(Empty(m.tcAsAlias),m.tcAlias,m.tcAsAlias) )
 
      Acopy(aStripped, .aStructure)
      Select * From (m.tcAlias) Where !Deleted() Into Cursor __crsTemp__ nofilter
      .RecordS = Reccount()
      If .RecordS > 0
        Dimension .aRecords[RECCOUNT()]
        Scan
          Scatter Name .aRecords[RECNO()] Memo
        Endscan
      Endif
      Use In '__crsTemp__'
    Endwith
  Endproc
 
  Procedure RestoreDataSet(tnDataSessionID) && restore all with saved aliases
    For ix = 1 To This.TableCount
      This.Obj2Cursor( This.TableInfo[m.ix].Alias, '', m.tnDataSessionID )
    Endfor
  Endproc
 
  Procedure Obj2Cursor( tcStoredAlias, tcAlias, tnDataSessionID )
    Local ix,jx
    If !Empty(m.tnDataSessionID)
      Set DataSession To m.tnDataSessionID
    Endif
    For ix = 1 To This.TableCount
      With This.TableInfo[m.ix]
        If Upper(.Alias) == Upper(m.tcStoredAlias)
          tcAlias = Iif(Empty(m.tcAlias), .AsAlias, m.tcAlias )
          Create Cursor (m.tcAlias) From Array .aStructure
          For jx = 1 To .RecordS
            Append Blank
            Gather Name .aRecordS[m.jx] Memo
          Endfor
          Exit
        Endif
      Endwith
    Endfor
    Set DataSession To This.DataSessionId
  Endproc
Enddefine

11

Re: use ile açılan dosyaları kapatmak

Üstad;
Açıklayıcı ve eğitici bilgiler için kendi adıma çok teşekkür ediyorum. smile

Uğur
-------------------------------------------------------------------------------------------------------------
Hayat bir bisiklete binmek gibidir. Pedalı çevirmeye devam ettiğiniz sürece düşmezsiniz. Claude Peppeer
Kusuru söylenmeyen adam, ayıbını hüner sanır.  Türk Atasözü

12 Son düzenleyen, konuka (27.07.2007 02:55:14)

Re: use ile açılan dosyaları kapatmak

Merhaba Çetin Bey,
anladığım kadar yukarıda kodlar VFP 6da çalışmıyor, baya uğraştım... (yarın bana 9 geliyor, ayrıca enteresan bir bilgi daha var; MS VFP 9.0 türkiyede satmayı yasaklamış - kaynağı ile yarın konuşup sizlerle tam doğru bilgiyi paylaşacağım)
Ben aşağıdaki metodu kullanıyorum, mahzuru var ise uyarmanı rica ediyorum -sevgiler:
-----------------------------------------
Form1.DataYolla
Xalias=ALIA()
SELE 0
Xfile=SYS(2023)+SYS(2015)+".DBF"
SELE * FROM Form1dekiData INTO DBF (Xfile)
USE
IF !ISBL(Xalias)
  SELE (Xalias)
ENDI
RETU Xfile
---------------------------
Form2.DataAl
XgelenData=Form1.DataYolla()
USE (XgelenData) ALIAS XgelenData1
SELE * FROM (XgelenData) INTO CURS Form2deKullanData
SELE XgelenData1
USE
ERASE &XgelenData

SELE Form2deKullanData
BROW

VFP9 SP2

13

Re: use ile açılan dosyaları kapatmak

VFP6 da calisir biraz edit edince
Senin kod fena degil, m. kullansan ve &'dan kutulsan daha iyi olacak bence ( Orada gercekten dogru dosyayi siliyor mu? - bana diskte:

c:\documents
c:\dokumanlar

gibi bir dosya olsa onu silecek gibi geldi.
& yerine:

erase (m.dosyaAdi)

Makro onu:

erase c:\Documents and settings\....

seklinde kullanacak ve ilk bosluk nedeniyle:

c:\documents diye bir dosya varsa o silinecek (diye dusunuyorum).

14

Re: use ile açılan dosyaları kapatmak

ben uyardığın belirsizlik için öncelikle çok keskin bir dosya adı adreslemesi yapıyorum:
Xfile=SYS(2023)+SYS(2015)+".DBF"

ayrıca belki lüzumsuz bir de alias adı kullanıyorum:
USE (XgelenData) ALIAS XgelenData1
..
SELE XgelenData1

M.dosyaad metodunu nedense kullanmıyordum- ÇOK teşekkür ederim. (başka şeyler de rahatladı)

bu arada bir de SET DATE GERMAN da datasessiona özel diye biliyorum...(başlık içerisinde geçiyor)

VFP9 SP2

15

Re: use ile açılan dosyaları kapatmak

Evet orada cok kesin bir dosya adi olusuyor. Benim demek istedigim esegini saglam kaziga bagla.

Sys(2023) geriye path getirirken orijinal isimleri yerine eski DOS 8.3 kullaniyor:

c:\Docume~1\cetin\locals~1\....

seklinde. Bir an icin bu ozelligini hatirlamadigini veya benzer bir islemi getfile() ile filan yaptigini dusun. O zaman:

c:\Documents and Files\cetin\Local settings\....

gibi birsey olacak. Yani artik icinde bosluk var. Bu tip pathler:

&cPath ile kullanildiginda:

c:\Documents

der keser.

(m.cPath) ise her zaman guvenli.

use (m.cPath)
erase (m.cPath)
copy file (m.cPath) ...

O kadar da onemli degil ama gozume batti, iste:)

SET DATE GERMAN
da datasessiona ozel ama ben daima defaultuyla calistigimdan yok orada. Bir de ne zaman degistirmeye kalksam:

set date british
set date german
set date american

vs yerine ben daima:
set date dmy
set date mdy
tercih ediyorum. Sadece tercih meselesi.

16

Re: use ile açılan dosyaları kapatmak

kod eksik kalmasın diye tamamlamak istiyorum, ERASE komutu konuştuğumuz şekilde keskin dosya adlarına özgü, küçük büyük harf de etki ediyor, bu nedenle eğer memo kullanılıyorsa ilaveten aşağıdaki kad da gerekiyor:

Visual Fox Pro
ERASE (CHRTRAN(XgelenData,".DBF",".FPT"))

sevgiler

VFP9 SP2

17

Re: use ile açılan dosyaları kapatmak

erase (juststem(m.tabloadi),'.*')

18

Re: use ile açılan dosyaları kapatmak

konuka yazdı:

... küçük büyük harf de etki ediyor, ...

sevgiler


küçük-büyük harf windows'ta etkilemez. UNIX'te etkiler...

Haksızlıklar karşısında susanlar, dilsiz şeytanlardır!
www.metinemre.com