| Register | FAQ | Calendar | Search | Today's Posts | Mark Forums Read |
|
#1
| |||
| |||
| 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 |
|
#2
| |||
| |||
| 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 |
|
#3
| |||
| |||
| 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 |
|
#4
| |||
| |||
| 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 |
|
#5
| |||
| |||
| 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 |
|
#6
| |||
| |||
| Hallo, Pedro, .... leav the commit() instruction inside the loop und do it after. Commit() in a loop did irritate me often yet. CYA Gunter |
|
#7
| |||
| |||
| 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 |
|
#8
| |||
| |||
| 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 := self DCBrIngredientes:Server:Recno // bBrowser withbArrayServer self DCBrIngredientes:Server:SetFilter({|Server|Server:Modificad}) // updated price self DCBrIngredientes:Server:GoTop()do while .not. self DCBrIngredientes:Server:EofnClave := self DCBrIngredientes:Server:FIELDGET(#Clave)// Actualizar Ingredientes if gIngreds:Seek(nClave) gIngreds:LockCurrentRecord() gIngreds:FIELDPUT(FINumProvdr, self DCBrIngredientes:Server:FIELDGET(#Proveedor) )gIngreds:FIELDPUT(FIPrecio, self DCBrIngredientes:Server:FIELDGET(#Precio))gIngreds:FIELDPUT(FIUnidad_cmp, self DCBrIngredientes:Server:FIELDGET(#UnidadCmp) )gIngreds:FIELDPUT(FICantd_cmp, self DCBrIngredientes:Server:FIELDGET(#CantidadC) )gIngreds:FIELDPUT(FIPrecio_100, self DCBrIngredientes: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(; (self DCBrIngredientes:Server:FIELDGET(#Precio100 ) - ;self DCBrIngredientes: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 self DCBrIngredientes:Server:FIELDPUT(#Modificad, false)self DCBrIngredientes:Server:Skip()enddo Return nil |
|
#9
| |||
| |||
| 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 |
|
#10
| |||
| |||
| 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 |
![]() |
| Thread Tools | |
| Display Modes | |
In an effort to better serve ads to our visitors, cookies are used on objectmix.com. For more information, check out our Privacy Policy.