Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
Strategies for reverting data
Message
From
02/01/2008 11:35:00
 
General information
Forum:
Visual FoxPro
Category:
Databases,Tables, Views, Indexing and SQL syntax
Environment versions
Visual FoxPro:
VFP 9 SP2
OS:
Windows XP SP2
Database:
Visual FoxPro
Miscellaneous
Thread ID:
01278863
Message ID:
01278988
Views:
20
Hi Joe,

I Think we do what you are describing. The only caveat is all our data access is accomplished with local views.

We have a form class named frmChild for dealing with Children, GrandChildren etc. That class implements the following methods.
***************************************************************************
*!*	Method:			frmChild.BuildRevertCursor
*!*	Purpose:		Builds revert cursor.  SELECT * FROM... does not work
*!*					because SELECT draws from the base table.
*!*	Author:			bxk 09.11.02
*!*	Parameters:		tcSource, cursor name used as source
*!*					tcDest, cursor name to be built
*!*	Returns:
***************************************************************************
LPARAMETERS tcSource, tcDest

PRIVATE ALL LIKE m.*	&& for the SCATTER MEMVAR
LOCAL laFields, lnRows
LOCAL lcField, lj, lnFields, lcColumn

DIMENSION laFields[1,1]
STORE 0 TO lnRows, lj, lnFields
STORE "" TO laFields, lcField, lcColumn

ASSERT PCOUNT() = 2 ;
	MESSAGE 'BuildRevertCursor() REQUIRES both Source Cursor Name, and Destination Name!'
	
AFIELDS(laFields, tcSource)

lnRows = ALEN(laFields, 1) + 1				
lnCols = ALEN(laFields, 2)

*!* Add column for fieldstate string
DIMENSION laFields[lnRows, lnCols]
laFields[lnRows, 1] = 'CFLDSTATESTR'
lafields[lnRows, 2] = 'M'
lafields[lnRows, 3] = 4
lafields[lnRows, 4] = 0
lafields[lnRows, 5] = .F.
lafields[lnRows, 6] = .F.
lafields[lnRows, 7] = ""
lafields[lnRows, 8] = ""
lafields[lnRows, 9] = ""
lafields[lnRows, 10] = ""
lafields[lnRows, 11] = ""
lafields[lnRows, 12] = ""
lafields[lnRows, 13] = ""
lafields[lnRows, 14] = ""
lafields[lnRows, 15] = ""
lafields[lnRows, 16] = ""

*!* clear defaults
FOR li = 1 TO lnRows
	laFields[li, 9] = ""
ENDFOR										

CREATE CURSOR (tcDest) FROM ARRAY laFields

SELECT (tcSource)
SCAN
	SCATTER MEMVAR MEMO
	m.cFldStateStr = GETFLDSTATE(-1, tcSource)	
	INSERT INTO (tcDest) FROM MEMVAR

	
ENDSCAN	
GO TOP IN (tcSource)			

*!* Update array of Revert Cursor names
WITH THISFORM
	lnRows = ALEN(.aRevertCursors, 1) + 1
	DIMENSION .aRevertCursors[lnRows, 2]
	.aRevertCursors[lnRows, 1] = tcSource
	.aRevertCursors[lnRows, 2] = tcDest
	
ENDWITH

RETURN


***************************************************************************
*!*	Method:			frmChild.RestoreFromRevert
*!*	Purpose:		Loop through RevertCursor array restoring views to before 
*!*					form launch state.
*!*	Author:			bxk 09.11.02
*!*	Parameters:		
*!*	Returns:
***************************************************************************
LOCAL lnRows, lcView, lcCursor, lcLocate, loRevertlcFldState, lnFields, ;
	li, lj, laFields[1], lcField, lcColumn

STORE 0 TO lnRows, lnFields, li, lj
STORE "" TO lcView, lcCursor, lcLocate, lcFldState, lcField, lcColumn
STORE .NULL. TO loRevert

WITH THISFORM

	lnRows = ALEN(.aRevertCursors, 1)

	FOR li = 1 TO lnRows
		lcView = .aRevertCursors[li, 1]
		lcCursor = .aRevertCursors[li, 2]

		IF !EMPTY(lcView)		&& 02.06.03 bxk check for empty rows
			lcLocate = TRIM(lcView) + '.iRecID'
			
			SELECT (lcView)
			GO TOP IN (lcView)
			DO WHILE !EOF(lcView)
				SELECT (lcCursor)
				LOCATE FOR iRecID = EVALUATE(lcLocate)
				IF FOUND(lcCursor)
					SCATTER NAME loRevert MEMO
					SELECT (lcView)
					GATHER NAME loRevert FIELDS EXCEPT cFldStateStr
					
					lcFldState = ALLTRIM(loRevert.cFldStateStr)
					RestoreFldState(lcFldState, lcView)
					SKIP 1 IN (lcView)
					
				ELSE
					*!* newly added record, OK to revert
					lnVal = TABLEREVERT(.F., lcView)
					IF lnVal = 0	&& Tablerevert was NOT successful
						SKIP 1 IN (lcView)
						
					ENDIF
				
				ENDIF
				
			ENDDO
			
			GO TOP IN (lcView)			
			
			USE IN SELECT(lcCursor)
			
		ENDIF
		
	ENDFOR

ENDWITH

STORE .NULL. TO loRevert

RETURN


***************************************************************************
*!*	Method:			RestoreFldState
*!*	Purpose:		Set buffer status for a record to passed value
*!*	Author:			bxk 02.20.03
*!*	Parameters:		tcFldState - string created by call to GETFLDSTATE(-1, tcAlias)
*!*					tcAlias - alias of buffered record to process
*!*	Returns:
*!*	Modifications:	
***************************************************************************
LPARAMETERS tcFldState, tcAlias

LOCAL li, lnVal, lnBufferMode
STORE 0 TO li, lnVal, lnBufferMode

lnBufferMode = CURSORGETPROP('buffering', tcAlias)
ASSERT lnBufferMode > 1 ;
	MESSAGE 'RestoreFldState ONLY works on Buffered Views'
IF lnBufferMode < 2
	*!* Bail if buffering not enabled
	RETURN .F.
ENDIF

tcFldState = ALLTRIM(tcFldState)
ASSERT LEN(tcFldState) = LEN(GETFLDSTATE(-1, tcAlias)) ;
	MESSAGE 'RestoreFldState - structure of tcAlias does NOT match tcFldState'
IF LEN(tcFldState) # LEN(GETFLDSTATE(-1, tcAlias))
	RETURN .F.
ENDIF

*!* start at 0 to get Delete flag
FOR li = 0 TO LEN(tcFldState) - 1
	lnVal = VAL(SUBSTR(tcFldState, li + 1, 1))
	SETFLDSTATE(li, lnVal, tcAlias)
	
ENDFOR

RETURN


***************************************************************************
*!*	Method:			frmChild.ProcessCancel
*!*	Purpose:
*!*	Author:			bxk 11.09.01
*!*	Parameters:
*!*	Returns:
*!*	Modifications:	
***************************************************************************
LPARAMETERS tlNoAsk

WITH THIS
	.HIDE()
	.RestoreFromRevert()
	.RELEASE()

ENDWITH

RETURN
In an instance of this form, we call BuildRevertCursor as needed...
*!* Here is instance code from a form.Init...
THISFORM.BuildRevertCursor('hcchrgadjudeditview', 'curRevertchrgadjud')
THISFORM.BuildRevertCursor('hcchrgadjuseditview', 'curRevertchrgadjus')
'Save' is only called from the Parent form. The 'Cancel' button simply calls process cancel. The child forms use the Parent form's datasession.

Hope this helps

Bruce


>I understand table buffering well enough but it breaks down quickly when using parent-child-grandchild-etc tables with forms. Then you are faced with having to save the record somehow to revert it without actually calling tablerevert. What is a good strategy to do this?
>
>1. Scatter to memory... object... array?
>2. Copy the record to a temp table?
>
>
>Then should I bind the actual fields to the controls and copy the data back to the table if I need to revert or should I bind to whatever I scatter to and copy the scatter vars back to the table in the need to save?
Previous
Next
Reply
Map
View

Click here to load this message in the networking platform