Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

tableupdate not updating in time? 3

Status
Not open for further replies.

foxup

Programmer
Dec 14, 2010
328
CA
Hi,

I have this simple code in a push-button:

** CREATE NEXT AVAILABLE UID **
IF USED("NEXTLOCALNUM")
SELECT NEXTLOCALNUM
ELSE
USE NEXTLOCALNUM IN 0
ENDIF
XX=''
XX=NEXTLOCALNUM.NEXTLOCALN+1
SET MULTILOCKS ON
=CURSORSETPROP('Buffering', 5, 'NEXTLOCALNUM')
REPLACE NEXTLOCALNUM.NEXTLOCALN WITH XX
=TABLEUPDATE(.T.)
L_ORDNUM="L"+ALLTRIM(STR(XX))
THISFORM.TEXT1.VALUE=L_ORDNUM
THISFORM.REFRESH
** CREATE NEXT AVAILABLE UID END**

It's a multi-user environment & basically, it provides an ongoing unique sequential ORDER NUMBER (for each order created). Simple enough, YET, the problem I'm seeing is that if 1 user pushes that button and then another user pushes that button, the 1st and 2nd user sometimes (not all the time) get the same order number (which is weird because I'm TABLEUPDATEing, so the value should be different, correct?

I hope you understand what I'm saying. :)

Please help in fixing this bug because I don't know why it's happening.


Thanks,
FOXUP!
 
Hi Tamar,

You're quite right as usual. let me play devil's advocate for a second and go back to my old code which was:

** CREATE NEXT AVAILABLE UID **
IF USED("NEXTLOCALNUM")
SELECT NEXTLOCALNUM
ELSE
SELECT 0
USE NEXTLOCALNUM
ENDIF

XX=''
XX=NEXTLOCALN+1

SET MULTILOCKS ON
=CURSORSETPROP('Buffering', 5, 'NEXTLOCALNUM')
REPLACE NEXTLOCALNUM.NEXTLOCALN WITH XX
=TABLEUPDATE(.T.)


I changed it to simply this:

** CREATE NEXT AVAILABLE UID **
IF USED("NEXTLOCALNUM")
SELECT NEXTLOCALNUM
ELSE
SELECT 0
USE NEXTLOCALNUM
ENDIF

XX=''
XX=NEXTLOCALN+1

SET MULTILOCKS ON
=CURSORSETPROP('Buffering', 5, 'NEXTLOCALNUM')
REPLACE NEXTLOCALNUM.NEXTLOCALN WITH XX
=TABLEUPDATE(.T.)
SELECT NEXTLOCALNUM && added this
USE &&added this

this seems to write the data to the disk instantly I'm assuming as I did some more tests and seems to be working quite nicely.

Any thoughts ? I really appreciate all your time.


Thanks,
FOXUP!
 
True. If all else fails, why reinvent what foxpro already offers in
Home()+"Samples\Solution\Db\newid.dbc"

Bye, Olaf.
 
Sorry Olaf, can you please post it cause I have nothing in my "SAMPLES" folder.

Thanks,
FOXUP
 
What version of foxpro do you have? Samples are always installed. In VFP6 they may be somewhere else, I remeber MSDN Library was installing the VFP6help and maybe also Samples. VFP6 was part of Visual Studio, that's why things where different with it.

Code:
FUNCTION NewID(tcAlias)
  LOCAL lcAlias, ;
  		lnID, ;
        lcOldReprocess, ;
        lnOldArea

  lnOldArea = SELECT()
  
  IF PARAMETERS() < 1
    lcAlias = UPPER(ALIAS())
  ELSE
    lcAlias = UPPER(tcAlias)
  ENDIF
        
  lcOldReprocess = SET('REPROCESS')
  
  *-- Lock until user presses Esc
  SET REPROCESS TO AUTOMATIC

  IF !USED("IDS")
    USE newid!ids IN 0
  ENDIF
  SELECT ids
      
  IF SEEK(lcAlias, "Ids", "table")
    IF RLOCK()
      lnID = ids.nextid
      REPLACE ids.nextid WITH ids.nextid + 1
      UNLOCK
    ENDIF
  ENDIF
    
  SELECT (lnOldArea)
  SET REPROCESS TO lcOldReprocess
  
  RETURN lnID
ENDFUNC

This needs to be a stored proc in the dbc also containing an ids.dbf, which has a record per other table of the dbc. Two fields table C(10) and nextid Integer, index on the table field tag name table (can be deducted from the SEEK() call).

Bye, Olaf.
 
deduced, not deducted.

One more thing: You need to init ids.dbf with a record per table and you can then call newid() as the default value of a table's ID field.

Bye, Olaf.
 
OK, thank you. I hope this works this time. :)


Thanks again,
FOXUP!

 
I'm curious, in my first ORIGINAL post, can anybody tell me why the record value is not updated even though I tableupdate()

Curious.

Thanks,
FOXUP
 
Foxup,

your last question was already answered, and you also understood my explanaition....

again.

You where calling tableupdate(), while another workarea than NEXTLOCALNUM was active, because in the first run you did USE NEXTLOCALNUM IN 0, which openes, but not selects it. (You already saw that)

Later, the tableupdate() updated whatever table was selected inititally, but not NEXTLOCALNUM. Tableupdate() only updates one alias, and if you don't specify an alias, it updates the currently selected alias, ALIAS(). So you updated some other table open at that moment, instead of NEXTLOCALNUM, which didn't fail, perhaps, but didn't store NEXTLOCALNUM.

Only at a second run the if branch was doing SELECT NEXTLOCALNUM, as it was open by the first run, and from then on you updated NEXTLOCALNUM.

In short, simply put ? ALIAS() right before tableupdate(), close NEXTLOCALNUM, then call your normal code, and you'll see the first run writes somewhere else.

Bye, Olaf.
 
an even better test:
Close Tables All
CD ("directory of NEXTLOCALNUM")
USE Home()+"browser.dbf"
now run your code.

At default settings, browser is not buffered and you'll get an error "function requires table or row buffering mode".

The only siuation your code runs and selects NEXTLOCALNUM in the first run is, if no table is open in the first place, beause then USE IN 0 (jus coincidentially) also selects the opened table, because it's the only workarea used, then.

But that is not a realistic condition, as you will have at leaast the one table open, in which you want to generate the new id.

Bye, Olaf.
 
OK, thanks again for all your help. :)
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top