dbServer:seek failure in 2.8 -CDX

This is a discussion on dbServer:seek failure in 2.8 -CDX within the Clipper forums in Programming Languages category; I have the following code: ..... local nKey as dWord nKey := 40001 do while (some condition) ... if self:mydbServer:Seek(nKey) self:mydbServer:LockCurrentRecord() self:mydbServer:FieldPut(72, new value) self:mydbServer:Commit() self:mydbServer:Unlock() else tone(300,3) endif enddo ....... The first time arround it finds the record and does the update, but the second time it doesn't find it. The workarround I found was to add the following line self:mydbServer:Skip() just after the unlock. Is this a known bug? My DBF file has only 6 records for testing. The keyfield is defined as KEYFIELD, "N", 7, 0 the index file has two orders (I'm using the second one) ...

Go Back   Application Development Forum > Programming Languages > Clipper

Object Mix

Register FAQ Calendar Search Today's Posts Mark Forums Read
  #1  
Old 08-28-2008, 12:38 AM
Pedro M. Espinosa
Guest
 
Default dbServer:seek failure in 2.8 -CDX

I have the following code:
.....
local nKey as dWord
nKey := 40001
do while (some condition)
...
if self:mydbServer:Seek(nKey)
self:mydbServer:LockCurrentRecord()
self:mydbServer:FieldPut(72, new value)
self:mydbServer:Commit()
self:mydbServer:Unlock()
else
tone(300,3)
endif
enddo
.......
The first time arround it finds the record and does the update, but
the second time it doesn't find it.
The workarround I found was to add the following line
self:mydbServer:Skip()
just after the unlock.
Is this a known bug? My DBF file has only 6 records for testing. The
keyfield is defined as
KEYFIELD, "N", 7, 0
the index file has two orders (I'm using the second one) and its
working properly at least with the utility cmVodbx32 ver 3.17.1.0 from
JR-INFO

TIA for your help
Pedro
Reply With Quote
  #2  
Old 08-28-2008, 02:08 AM
Stephen Quinn
Guest
 
Default Re: dbServer:seek failure in 2.8 -CDX

Pedro

> The workarround I found was to add the following line
> self:mydbServer:Skip()
> just after the unlock.
> Is this a known bug? My DBF file has only 6 records for testing. The
> keyfield is defined as


Hardly a bug when you never step off the record you found/changed.

> local nKey as dWord
> nKey := 40001
> do while (some condition)
> ...
> if self:mydbServer:Seek(nKey)
> self:mydbServer:LockCurrentRecord()
> self:mydbServer:FieldPut(72, new value)
> self:mydbServer:Commit()
> self:mydbServer:Unlock()
> else
> tone(300,3)
> endif

self:mydbServer:Skip() // Required in any DO loop
> enddo


CYA
Steve


Reply With Quote
  #3  
Old 08-28-2008, 03:04 AM
Paul D B
Guest
 
Default Re: dbServer:seek failure in 2.8 -CDX

Pedro M. Espinosa wrote:
> I have the following code:
> ....
> local nKey as dWord
> nKey := 40001
> do while (some condition)
> ...
> if self:mydbServer:Seek(nKey)
> self:mydbServer:LockCurrentRecord()
> self:mydbServer:FieldPut(72, new value)
> self:mydbServer:Commit()
> self:mydbServer:Unlock()
> else
> tone(300,3)
> endif
> enddo
> ......
> The first time arround it finds the record and does the update, but
> the second time it doesn't find it.
> The workarround I found was to add the following line
> self:mydbServer:Skip()
> just after the unlock.
> Is this a known bug? My DBF file has only 6 records for testing. The
> keyfield is defined as
> KEYFIELD, "N", 7, 0
> the index file has two orders (I'm using the second one) and its
> working properly at least with the utility cmVodbx32 ver 3.17.1.0 from
> JR-INFO
>
> TIA for your help
> Pedro


Pedro,


see Steve's answer.. what's the use of a do-loop when you don't skip?

Guessing what you want to achieve...
a) you want to change one record only: you seek it and you update it.
That's all. No DO WHILE is necessarry.
b) you want to change a batch of records: DO WHILE, and Skip() of course
otherwise you just stay on the same record

Maybe you could show us all of the code?

--
Paul

Reply With Quote
  #4  
Old 08-28-2008, 04:24 AM
Geoff Schaller
Guest
 
Default Re: dbServer:seek failure in 2.8 -CDX

Pedro,

This depends utterly on your index and your 'some condition', which you
didn't disclose <g>. I doubt there is a bug here in VO. More likely it
is your business logic. If your key change now takes you to the bottom
of your condition set then....

Skip() obviously refreshes the server.

Geoff


"Pedro M. Espinosa" <pmespinosa@gmail.com> wrote in message
news:fb449805-565d-4c76-84d1-31578990f1f1@i76g2000hsf.googlegroups.com:

> I have the following code:
> ....
> local nKey as dWord
> nKey := 40001
> do while (some condition)
> ...
> if self:mydbServer:Seek(nKey)
> self:mydbServer:LockCurrentRecord()
> self:mydbServer:FieldPut(72, new value)
> self:mydbServer:Commit()
> self:mydbServer:Unlock()
> else
> tone(300,3)
> endif
> enddo
> ......
> The first time arround it finds the record and does the update, but
> the second time it doesn't find it.
> The workarround I found was to add the following line
> self:mydbServer:Skip()
> just after the unlock.
> Is this a known bug? My DBF file has only 6 records for testing. The
> keyfield is defined as
> KEYFIELD, "N", 7, 0
> the index file has two orders (I'm using the second one) and its
> working properly at least with the utility cmVodbx32 ver 3.17.1.0 from
> JR-INFO
>
> TIA for your help
> Pedro


Reply With Quote
  #5  
Old 08-28-2008, 04:37 AM
Stephen Quinn
Guest
 
Default Re: dbServer:seek failure in 2.8 -CDX

Pedro

A better construct is

if self:mydbServer:Seek(nKey)
do while ( self:mydbServer:Fieldget( #Whatever ) = nKey )
self:mydbServer:LockCurrentRecord()
self:mydbServer:FieldPut(72, new value)
self:mydbServer:skip()
enddo
self:mydbServer:Commit()
self:mydbServer:Unlock()
else
tone(300,3)
endif

CYA
Steve


Reply With Quote
  #6  
Old 08-28-2008, 07:01 AM
Gunter
Guest
 
Default Re: dbServer:seek failure in 2.8 -CDX

Hallo, Pedro,
.... leav the commit() instruction inside the loop und do it after.
Commit() in a loop did irritate me often yet.

CYA
Gunter
Reply With Quote
  #7  
Old 08-28-2008, 09:43 AM
oscar hernandez
Guest
 
Default Re: dbServer:seek failure in 2.8 -CDX

Hola Pedro,


In case You have several 40001s in Your table
local nKey as dWord
nKey := 40001
do while self:mydbServer:Seek(nKey,false)
self:mydbServer:LockCurrentRecord()
self:mydbServer:FieldPut(72, new value)
self:mydbServer:Commit()
self:mydbServer:Unlock()
enddo

or if You know there are just a few records
put the order to cero and do a different aproach.

local nKey as dWord
nKey := 40001
self:mydbserver:setorder(0)
self:mydbserver:gotop()
do while .not. self:mydbServer:eof
if self:mydbServer:Fieldget(72)=nkey
self:mydbServer:LockCurrentRecord()
self:mydbServer:FieldPut(72, new value)
self:mydbServer:Commit()
self:mydbServer:Unlock()
endif
self:mydbServer:skip()
enddo


Saludos
Oscar Hernandez


Reply With Quote
  #8  
Old 08-28-2008, 11:18 PM
Pedro M. Espinosa
Guest
 
Default Re: dbServer:seek failure in 2.8 -CDX

On Aug 28, 3:37*am, "Stephen Quinn" <stevej...@SPbigpond.AMnet.au>
wrote:
> Pedro
>
> A better construct is
>
> * * * if self:mydbServer:Seek(nKey)
> * * * * *do while ( self:mydbServer:Fieldget( #Whatever ) = nKey )
> * * * * * * *self:mydbServer:LockCurrentRecord()
> * * * * * * *self:mydbServer:FieldPut(72, new value)
> * * * * * * *self:mydbServer:skip()
> * * * * enddo
> * * * * self:mydbServer:Commit()
> * * * * self:mydbServer:Unlock()
> * * *else
> * * * * *tone(300,3)
> * * *endif
>
> CYA
> Steve


Steve and Paul
This was a simplification of the problem.
the Do loop is for another server who gives me the value of nKey and
obviously can change or stay the same (and there I have the skip!).
Let me try to explain a little of the bussiness logic. This is a
Recipes database, and in the previous code self:mydbServer is the
Master table.
The code belongs to the pricing of the ingredients, and when an
ingridient price changes I want to update the price of all the Recipes
that contain that ingredient. In order not to update every time a
single price is modified, I just marked the ingridients which prices
changed, and do all the update just before the user finishes updating
the prices.
In my test case I updated the price of two ingridients of the same
recipe, and that's the reason why I seek twice for the same record.

I hope that this explanation answers the "what's the use of a do-loop
when you don't skip?" and the need of the Do while.
As for the other suggestions, I don't need the
do while ( self:mydbServer:Fieldget( #Whatever ) = nKey )
as the Master table has unique keys

The Geoff comment. I also tried a Gotop() before the if
self:mydbServer:Seek(nKey)
statement but that apparently didn't refresh the server, and besides I
thought that the seek would allways find the record no matter where
the pointer is.

The Gunter comment. The reason I do the commit inside the loop is that
I use the field that I uptdate (the price) to recalc the new value
(price). I'm not certain if without the commit I get the updated
value. I know it takes a little longer but I wanted to be sure the
data is actually written.

The Oscar comment. As I explained above there is only one 40001 record
and the keyfield is never updated, once written.

Finally, here is the full code: - You can skip to the line
// Actualizar Recetas **** HERE COMES THE FAULTY (?) CODE
dbRecDetail is the detail table
dbRecetas is the master table (one to many relashionship)

method Guardar() class Precios
// gIngreds is the Ingridients dbServer
/* Every ingridient can have up to 5 differnt suppliers and one is
chosen by the user as the preferred one
*/
LOCAL nClave as dword // Ingredient number
LOCAL j as dword
LOCAL nNumPrv as dword // Suppiler nbr
LOCAL nReceta as dword // Recipe nbr
LOCAL nDifPrecio as Float // Price difference
LOCAL nPrecio as Float // price
LOCAL nRecno as dword
nRecno := selfDCBrIngredientes:Server:Recno // bBrowser with
bArrayServer
selfDCBrIngredientes:Server:SetFilter({|Server|
Server:Modificad}) // updated price
selfDCBrIngredientes:Server:GoTop()
do while .not. selfDCBrIngredientes:Server:Eof
nClave := selfDCBrIngredientes:Server:FIELDGET(#Clave)
// Actualizar Ingredientes
if gIngreds:Seek(nClave)
gIngreds:LockCurrentRecord()
gIngreds:FIELDPUT(FINumProvdr,
selfDCBrIngredientes:Server:FIELDGET(#Proveedor) )
gIngreds:FIELDPUT(FIPrecio,
selfDCBrIngredientes:Server:FIELDGET(#Precio))
gIngreds:FIELDPUT(FIUnidad_cmp,
selfDCBrIngredientes:Server:FIELDGET(#UnidadCmp) )
gIngreds:FIELDPUT(FICantd_cmp,
selfDCBrIngredientes:Server:FIELDGET(#CantidadC) )
gIngreds:FIELDPUT(FIPrecio_100,
selfDCBrIngredientes:Server:FIELDGET(#Precio100) )
gIngreds:Commit()
gIngreds:Unlock()
endif
// Actualizar Recetas **** HERE COMES THE FAULTY (?) CODE
self:dbRecDetail:Seek(Str(nClave,7),true)
do while self:dbRecDetail:FIELDGET(#RiCveIng) == nClave
nReceta := self:dbRecDetail:FIELDGET(#RiReceta)
nDifPrecio := Round(;
(selfDCBrIngredientes:Server:FIELDGET(#Precio100 ) - ;
selfDCBrIngredientes:Server:FIELDGET(#PrOrig100) ) * ;
self:dbRecDetail:FIELDGET(#PesoNeto) / 100,2)
// self:dbRecetas:GoTop() DIDN'T WORK
if self:dbRecetas:Seek(nReceta)
self:dbRecetas:LockCurrentRecord()
nPrecio := self:dbRecetas:FIELDGET(FCPRECIO) + ;
Round(nDifPrecio/self:dbRecetas:FIELDGET(FCRDPORCION),2)
self:dbRecetas:FIELDPUT(FCPRECIO, nPrecio)
self:dbRecetas:Commit()
self:dbRecetas:Unlock()
self:dbRecetas:Skip()
else
Tone(100, 3) /* THIS OF COURSE IS JUST TO CHECK IF SOMETHING IS
WRONG */
endif
self:dbRecDetail:Skip()
enddo
// Cambia de Registro
selfDCBrIngredientes:Server:FIELDPUT(#Modificad, false)
selfDCBrIngredientes:Server:Skip()
enddo
Return nil



Reply With Quote
  #9  
Old 08-29-2008, 02:10 AM
Stephen Quinn
Guest
 
Default Re: dbServer:seek failure in 2.8 -CDX

Pedro

I suggest you set a reltionship between the Ingredients and RecDetails
table, that way you wouldn't have to seek into the child table at all.
eg
gIndgreds:SetSelectiveRelation( dbRecDetail, {|| _FIELD->RiCveIng },
'_FIELD->RiCveIng' )
if gIngreds:Seek(nClave) // will automatically position the child on
the matching records
// You'll need to have a
numeric index on the child to match though

Why are you using a string index on the child server or for that matter why
a numeric on the master??
If you use a string for both and use a relation its much easier to maintain
(with cleaner code).

If your using CDX then it's easy to add temp orders (in a temp file) as
required.

IMO string indices are more reliable than numeric ones.

Did you forget the #s
or
are they defines (FCRDPORCION > 10 characters // illegal fieldname length)
> nPrecio := self:dbRecetas:FIELDGET(FCPRECIO) + ;
> Round(nDifPrecio/self:dbRecetas:FIELDGET(FCRDPORCION),2)
> self:dbRecetas:FIELDPUT(FCPRECIO, nPrecio)

eg
nPrecio := self:dbRecetas:FIELDGET( #FCPRECIO) + ;
Round(nDifPrecio/self:dbRecetas:FIELDGET( #FCRDPORCION),2)
self:dbRecetas:FIELDPUT( #FCPRECIO, nPrecio)

CYA
Steve


Reply With Quote
  #10  
Old 08-29-2008, 02:55 PM
Pedro M. Espinosa
Guest
 
Default Re: dbServer:seek failure in 2.8 -CDX

On Aug 29, 1:10*am, "Stephen Quinn" <stevej...@SPbigpond.AMnet.au>
wrote:
> Pedro
>
> I suggest you set a reltionship between the Ingredients and RecDetails
> table, that way you wouldn't have to seek into the child table at all.
> eg
> * * gIndgreds:SetSelectiveRelation( dbRecDetail, {|| _FIELD->RiCveIng},
> '_FIELD->RiCveIng' )
> * * if gIngreds:Seek(nClave) * // will automatically position the child on
> the matching records
> * * * * * * * * * * * * * * * * * * * * * * * * *// You'll need to have a
> numeric index on the child to match though
>
> Why are you using a string index on the child server or for that matter why
> a numeric on the master??
> If you use a string for both and use a relation its much easier to maintain
> (with cleaner code).
>
> If your using CDX then it's easy to add temp orders (in a temp file) as
> required.
>
> IMO string indices are more reliable than numeric ones.
>
> Did you forget the #s
> or
> are they defines (FCRDPORCION > 10 characters // illegal fieldname length)
> nPrecio := self:dbRecetas:FIELDGET(FCPRECIO) + ;
> > Round(nDifPrecio/self:dbRecetas:FIELDGET(FCRDPORCION),2)
> > self:dbRecetas:FIELDPUT(FCPRECIO, nPrecio)

>
> eg
> nPrecio := self:dbRecetas:FIELDGET( #FCPRECIO) + ;
> Round(nDifPrecio/self:dbRecetas:FIELDGET( #FCRDPORCION),2)
> self:dbRecetas:FIELDPUT( #FCPRECIO, nPrecio)
>
> CYA
> Steve


Steve:
> I suggest you set a reltionship between the Ingredients and RecDetails
> table, that way you wouldn't have to seek into the child table at all.


How would it work in a one to many relationship?

> Why are you using a string index on the child server or for that matter why
> a numeric on the master??


In the back of my mind I remember that numeric indexes were faster
(don't know if it was dBase, Clipper, or VO)
The reason for a string index on the child server is because is
concatenated with another field i.e. index on
Str(Field2,7)+Str(Field1,5)

> Did you forget the #s
> or
> are they defines


You're right! all FC names are defines. This was implemented as a way
to make the reverse engineering of some of my tables more difficult. I
live in a country that has piracy as a national sport... (as an
example the iTunes store cannot be reached from here)

A final comment "> IMO string indices are more reliable than numeric
ones." MAYBE THIS IS THE SOURCE OF MY PROBLEM.

Thanks for your interest
Pedro
Reply With Quote
Reply


Thread Tools
Display Modes


All times are GMT -5. The time now is 09:35 AM.


Powered by vBulletin® Version 3.7.2
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.2.0
vB Ad Management by =RedTyger=

In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.