On 2017-02-08 06:01, Alan Bourke wrote:
All this is why IMO the best approach is to have as much code as possible in programmatic classes and treat VCX files as atomic units.
By that, are you saying "just have VCXes for the visual stuff and put all the non-visual code in PRGs." Typically, that's how I develop. I have my framework VCX base classes with any custom-MBSS stuff, but the client-specifics are general SCX forms, and because I do the n-tier design, the visual forms invoke PRG-classes for the bizobj and dataobj layers, where all non-visual work is usually done. That design has worked well for me since 2004, making maintenance pretty easy, and allowing me to switch backends without much work if any (since I deal with VFP cursors, akin to Charlie Coleman's approach but not exactly). At one time I used Paul McNett's MakeUpdatable.prg routine in my framework, but years ago I changed to something along the lines of dynamically building the UPDATE SQL based on what properties had actually changed. (My data record is created via SCATTER and referenced in THISFORM.oRecord.) Changes were detected using AMEMBERS:
IF AMEMBERS(laProps,toRecord,0,"C") > 0 THEN liCnt = 0 FOR EACH cProp IN laProps IF EMPTY(lcFieldList) OR LOWER(cProp) $ LOWER(lcFieldList) THEN lvValue = EVALUATE("toRecord." + cProp) lcCmd = [private mjb] + ALLTRIM(cProp) &lcCmd lcCmd = [mjb] + ALLTRIM(cProp) + [ = lvValue] &lcCmd lcExpr = lcExpr + ALLTRIM(cProp) + [ = ?mjb] + ALLTRIM(cProp) + ", " ENDIF ENDFOR IF EMPTY(lcExpr) THEN && nothing to update! llSuccess = .T. ELSE * get rid of last comma lcExpr = LEFT(lcExpr,LEN(lcExpr)-2) lcSQL = this.BuildUpdateStatement(tcTable,lcExpr,this.cPKField,tvKey) llSuccess = this.ExecuteSQL(lcSQL) = 1 IF NOT llSuccess THEN AERROR(laError) *** mjb 12/05/2014 - just setting cErrMsg now IF EMPTY(laError[2]) THEN this.cErrMsg = "Unable to update " + ALLTRIM(TRANSFORM(tvKey)) ELSE this.cErrMsg = "Unable to update " + ALLTRIM(TRANSFORM(tvKey)) + "." + CRLF + "Error: " + laError[2] ENDIF && EMPTY(laError[2]) ENDIF && NOT llUpdated ENDIF && EMPTY(lcExpr) ELSE && nothing has changed; flag as ok llSuccess = .T. ENDIF && AMEMBERS(..) > 0