Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
MM Version 7.0 Save/Error handling issue ...
Message
General information
Forum:
Visual FoxPro
Category:
The Mere Mortals Framework
Title:
MM Version 7.0 Save/Error handling issue ...
Miscellaneous
Thread ID:
00649184
Message ID:
00649184
Views:
32
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
Map
View

Click here to load this message in the networking platform