Enrico and Elvira
You are correct on the Delete followed by update .. I went back and looked at some of my code and I do not use update and I do try to trap a possible error with try\catch\end try.
Here is some code where I delete a row presented through xBrowse..
- Code: Select all Expand view
//-----------------
Static FUNCTION _RateDel( oRsTaxRate,oLbxB )
LOCAL SAYING, cSQL, oERR, cNAME
IF xSUPER = 'Y'
ELSE
SAYING := "Sorry ... You have READ only Rights"
Msginfo( SAYING )
RETURN(.F.)
ENDIF
IF oRsTaxRate:EOF
SAYING := "Sorry ... Before you can Delete a "
SAYING += "record, you have to Add one first"
Msginfo( SAYING )
RETURN(.F.)
ENDIF
cNAME := oRsTaxRate:Fields("Description"):Value
SAYING := "Are you SURE you want to Delete this record for "+CHR(10)
SAYING += alltrim(cNAME)+CHR(10)
IF MsgYesNO( SAYING )
ELSE
RETURN(.F.)
ENDIF
Try
oRsTaxRate:Delete()
Catch
MsgInfo( "Deletion failed" )
Return(.f.)
End Try
TRY
oRsTaxRate:MoveNext()
CATCH
END TRY
IF oRsTaxRate:eof .and. .not. oRsTaxRate:bof
TRY
oRsTaxRate:MoveFirst()
CATCH
END TRY
ENDIF
oLbxB:ReFresh()
RETURN(NIL)
Elvira
Recordsets are a 'fetch' of rows based on the time you did the query. Workstation update visibility is something you have to consider in a networked environment ..
1) To Test for two workstations that are trying to modify the same record .. I create a field called UPDATED "N" and when the row is created I set UPDATED to 1 and when changed it gets incremented with UPDATED++. I allow both workstations to buffer their fields to memory variables and before I allow the the UPDATE() .. I have a function that goes out and creates another recordset based on the value of the rows primary key and I return the CURRENT value of UPDATED. I then compare the workstation value with the current returned value and if they are different .. then workstation B got to the update before workstation A making Workstation A's records 'stale' and in that case I do not allow workstation A to Update the same row... and you can then apply a Requery() to refresh Workstation A or close and re-open the recordset as I suggest in the next example.
2) As far as a DELETE that occurred from Workstation B .. Workstation A's visibility will not see any change in its buffered rows, hence your run-time error .. what you might consider is modifying my above example like this and if the Try\Catch errors .. you can either do a Requery() to refresh the current recordset or you can CLose() the current recordset and re-open it again which I have found to be more reliable than Requery() .. consider this change to the above delete function
- Code: Select all Expand view
Static FUNCTION _RateDel( oRsTaxRate,oLbxB )
LOCAL SAYING, cSQL, oERR, cNAME
IF xSUPER = 'Y'
ELSE
SAYING := "Sorry ... You have READ only Rights"
Msginfo( SAYING )
RETURN(.F.)
ENDIF
IF oRsTaxRate:EOF
SAYING := "Sorry ... Before you can Delete a "
SAYING += "record, you have to Add one first"
Msginfo( SAYING )
RETURN(.F.)
ENDIF
cNAME := oRsTaxRate:Fields("Description"):Value
SAYING := "Are you SURE you want to Delete this record for "+CHR(10)
SAYING += alltrim(cNAME)+CHR(10)
IF MsgYesNO( SAYING )
ELSE
RETURN(.F.)
ENDIF
Try
oRsTaxRate:Delete()
Catch
MsgInfo( "Deletion failed" )
// two possible options
// option 1
* oRsTaxRate:Requery()
// or close the recordset and reopen without re-initializing the
// recordset variable
oRsTaxRate:Close()
cSQL := "SELECT * FROM [jTax Sets] order by NAME" // original query
TRY
oRsTaxSet:Open( cSQL,xCONNECT )
CATCH oErr
// hope this never happens .. going to blow chunks
MsgInfo( "Error in Opening jTax Sets table" )
RETURN(.F.)
END TRY
IF oRsTaxRate:eof .and. .not. oRsTaxRate:bof
TRY
oRsTaxRate:MoveFirst()
CATCH
END TRY
ENDIF
oLbxB:ReFresh()
Return(nil)
End Try
TRY
oRsTaxRate:MoveNext()
CATCH
END TRY
IF oRsTaxRate:eof .and. .not. oRsTaxRate:bof
TRY
oRsTaxRate:MoveFirst()
CATCH
END TRY
ENDIF
oLbxB:ReFresh()
RETURN(NIL)