General information
Category:
The Mere Mortals Framework
Title:
MM Version 7.0 Save/Error handling issue ...
Hey Kevin:
I ran into a situation that you may want to address with Mere Mortals Version 7.0. It all started when I began getting an error with a form that was maintaining a list of current employer names. The data store is SQL Server 2000, using a remote view which is table buffered.
The first problem I ran into was located in the cDynamicViewCursor::BeginTransaction() method which looked like this:
ELSE
*--- Remote view ---*
lnHandle = CURSORGETPROP("CONNECTHANDLE")
lnRetVal = SQLSETPROP(lnHandle, "TRANSACTIONS", DB_TRANSMANUAL)
lnRetVal = IIF(lnRetVal = 1, FILE_OK, This.GetErrorNumber())
ENDIF
Believe it or not SQLSETPROP(), even though VFP’s help swears it return only numeric values, actually returned a .F. when I experienced a 1541 (Connection Busy) error. Therefore, I changed the code to the following to allow for this situation (the code is a logical equivalent that simply no longer trusts the return value of SQLSETPROP()):
ELSE
*-------------------*
*--- Remote view ---*
*-------------------*
lnHandle = CURSORGETPROP("CONNECTHANDLE")
lnRetVal = SQLSETPROP(lnHandle, "TRANSACTIONS", DB_TRANSMANUAL)
IF VARTYPE( lnRetVal ) = "N" AND lnRetVal = 1
lnRetVal = FILE_OK
ELSE
lnRetVal = THIS.GetErrorNumber()
ENDIF
ENDIF
Now that the cDataAccessBase::GetErrorNumber() method is being called it surfaced another problem … notice that equal sign before the return value … it was causing a little problem as well … so … I changed this:
LOCAL laError[AERROR_NUMCOLUMNS]
=AERROR(laError)
RETURN = laError[AERROR_ERROR]
to this:
LOCAL laError[ AERROR_NUMCOLUMNS ]
=AERROR( laError )
RETURN laError[ AERROR_ERROR ]
Continuing on the trace back up the calling stack we arrive at KbizObj::Save() method which has the following code:
IF llIsRemote
lnRetVal = This.RemoteExecutantSave(tlAllRows, tlForce)
ELSE
*------------------------
*-- BEGIN the Transaction
*------------------------
IF This.lUseTransactions
IF loExecutant.BeginTransaction() != FILE_OK
RETURN .F.
ENDIF
ENDIF
lnRetVal = loExecutant.Save(tlAllRows, tlForce)
ENDIF
Notice the RETURN .F. block of code … Mere Mortals convention for the Save() method (as well as Delete, New and Cancel methods) dictate a numeric return value. This return .F. breaks the signature of the Save() method as well as some things at the form level as a result. Therefore, I changed the Save() code to the following:
IF llIsRemote
lnRetVal = This.RemoteExecutantSave(tlAllRows, tlForce)
ELSE
*------------------------
*-- BEGIN the Transaction
*------------------------
IF This.lUseTransactions
lnRetVal = loExecutant.BeginTransaction()
IF lnRetVal != FILE_OK
RETURN lnRetVal
ENDIF
ENDIF
lnRetVal = loExecutant.Save(tlAllRows, tlForce)
ENDIF
Finally, this journey takes us to the CBizObjForm::Save() method. Nothing required changing here but it is interesting to note that now, since the error number is present in the return value the CASE statement located immediately after the following code
IF llPassParms
lnRetVal = this.SaveBizObj(tlAllRows, tlForce)
ELSE
lnRetVal = This.SaveBizObj()
ENDIF
properly processes the unhanded error by triggering the ERROR procedure as follows.
OTHERWISE
*-- An unhandled error
ERROR lnRetVal
ENDCASE
You and all you other MM gurus out there might want to take a gander at these fixes and bless them or reject them based upon your experience.
Have a great one,
CTBlankenship
Claims Verification, Inc.
Deerfield Beach, FL 33442
CBlankenship@cvi.com
PS:
And yes, I have a screen capture of the SQLSETPROP() function returning a logical .F. if anyone requires proof ;-).
Next
Reply
View the map of this thread
View the map of this thread starting from this message only
View all messages of this thread
View all messages of this thread starting from this message only