Jack wrote:Otto,
When the user push the Add button, the process takes 1 or 2 seconds .
After that, you can go for lunch .
Philippe .
TimStone wrote:Three options:
1). Open the file, lock it, append the record, add the code to the field, save the record, unlock it. This happens in milliseconds and no other user on the network will have access.
2) Fill the data with blanks in variables, edit the variables with all the data, then in your Save method, lock the file, append the record, calculate and put the number in the buffer, then save the full record, and unlock the file.
3). MY PREFERRED METHOD: Your goal is to have unique, sequential, numbers. I have a "counters" file. When I want to add a record, I open the file, get the proper value ( there are fields for each file ), increment it by one, then save the new value. Locking applies. Again, it takes milliseconds to do this, and with hundreds of thousands of records written each year, my clients have NEVER encountered a problem. Some locations have up to 20 workstations sharing data in a network. The values are assigned to variables in the .prg and applied to records as approrpiate.I use a 10 digit counter for each file. Also, I have a function that allows them to set new values for a counter in case they want to start a fresh location each yeear. IT WORKS, and that is what I find most important.
oDb_Semaforo:GoTo(120) //Registration with the clients registration sequence
oDb_Semaforo:rLock(8) //Method rLock 8 (Represents 8 seconds corresponding to the routine. if it exceeds the lock attempts it returns .F.)
nClienteCodigo := oDb_Semaforo:SetValSequence(-1)
? nClienteCodigo
Method SetValSequence(f_nValor,f_nRecno,f_lUnlock) Class DB_SEMAFORO
Local nValorRetorno := 0
Default f_lUnlock := .T.
If !Hb_isNil(f_nRecno)
::GoTo(f_nRecno)
EndIf
::rLock()
if f_nValor == -1 // add +1
nValorRetorno := ::VarPut("VALOR_ATUA",1,"+")
Else
nValorRetorno := ::VarPut("VALOR_ATUA",f_nValor)
EndIf
If f_lUnlock
::Commit(.T.)
Else
::Commit()
EndIf
RETURN nValorRetorno
METHOD Lock(f_nRecno) Class TAds
Local lLockRecno := .F., iForTentativa := 0
Default f_nRecno := (::cAlias)->(Recno())
If (::cAlias)->(Recno()) != f_nRecno
(::cAlias)->(DbGoTo(f_nRecno))
::OnSkip()
EndIf
For iForTentativa := 1 To 5
(::cAlias)->(AdsRefreshRecord())
If (::cAlias)->(DbRLock())
lLockRecno := .T.
Exit
Else
SysWait(.2)
EndIf
Next
RETURN lLockRecno
James Bott wrote:Silvio,
If I understand correctly, you are converting an exclusive use app written in Clipper to a multi-user application written in Fivewin?
I am not sure you can convert this to multi-user without some major design changes too.
I see some inconsistencies with the current database example. It seems that you are combining the first and second categories descriptions into the same field. This creates problems such as you cannot find all the records with SAMSUNG. For example, one record contains SAMSUNG in the DESCRATM field and CODCATM2 is blank and another record containing SAMSUNG has CONDCATM2 as 00025. Is the program depending on the user to make the right decisions on what to enter in the description field and the CODCATM2 field? The only way you can find all SAMSUNG products is to do an instring search of all the records in the database. Maybe you never need to do that?
What is the CODCATM2 field used for?
Also, you have a record without a CODCATM2 value that has the DESCRIPTION "COMABLEILI SAMSUNG." Why doesn't this have a CODCATM2 number?
How do you determine the description? How does your code decide when the record needs CODCATM2 and when it doesn't? Or, is the user deciding.
Note that all these kinds of issues would be resolved by using three related databases instead of one database. Users would be selecting data from lists (comboboxes) instead of manually entering them.
By the way, this is not a problem with TDatabase or TData--this is an application design issue due to converting from single user to multi-user.
Return to FiveWin for Harbour/xHarbour
Users browsing this forum: Google [Bot] and 110 guests