Hallo,
Danke für die vielen Antworten. Die mir zeigen, das mein Codebeispiel leider, nun ja, unvollständig ist. Ich mach nämlich an dieser Stelle kein DbAppend(). Sondern rufe eine eigene Funktion auf, die so aussieht:
Code: Alles auswählen
UNCTION MyDbAppend
LOCAL lReturn := .F.
LOCAL bOldError := NIL
LOCAL nRetry := 0
LOCAL lExit := .F.
LOCAL e := NIL
LOCAL cStack := ""
UnUsed(e)
bOldError := ErrorBlock( {|e| MyDbSeekErrorblock(e, @lExit)}) // Original-Fehler-Codeblock sichern, eigenen installieren
DO WHILE .T. // So lange laufen lassen, bis ein kontrolliertes "Exit" kommt
BEGIN SEQUENCE // Eigene Laufzeitfehler-Behandlung starten
DbAppend() // Den Lock versuchen, Ergebnis speichern
nRetry ++ // Gleich hochzählen, auch wenn gültiiger versuch. Später aufwändiger
RECOVER USING bOldError // Was tun bei einem Laufzeitfehler
lReturn := NIL
nRetry ++
END SEQUENCE
ErrorBlock(bOldError) // Original-Fehler-Codeblock wiederherstellen
IF ValType(lReturn) # "U" // Wenn Sperre erfolgreich ...
lReturn := .T.
Exit // ... raus aus der Schleife
ELSEIF nRetry > 10 // Nach 10 vergeblichen Sperrversuchen
cStack := "Funktion " + ProcName(1) + ; // Um die Codezeile und den Datensatz zu identifizieren
" Zeile " + Var2Char(ProcLine(1)) + crlf + ;
"Datenbank " + Alias() + ;
" RecNo " + Var2Char(RecNo())
IF ConfirmBox(MEMVAR->oXbp, ; // Weiteres Vorgehen abfragen
"Ein Datensatz konnte nicht angehängt werden." + crlf + crlf + ;
cStack + crlf + crlf + ;
"Noch einmal versuchen?", ;
"Neuer datensatz", ;
XBPMB_YESNO, ;
XBPMB_QUESTION, ;
XBPMB_DEFBUTTON1) == XBPMB_RET_NO
IF hatRechte(MEMVAR->aAktMitarbeiter, "Vertrieb") >= 7 // Nur Admins dürfen unkontrolliert abbrechen
EXIT // Wenn "Noch einmal versuchen" mit "Nein" beantwortet wurde -> unkontrolliertes Ende!
ELSE
MsgBox("Sie haben keine ausreichenden Rechte, ein unkontrolliertes Beenden auszuwählen." + crlf + crlf + ;
"Bitte einen Admin informieren", ;
"Datensatzsperre fehlgeschlagen")
ENDIF
ENDIF
nRetry := 0 // Zähler zurück setzeen
ENDIF
Sleep(10) // 10/100 Sekunden warten
ENDDO
RETURN lReturn
Damit bekomme ich dann eben kein NIL zurück. Sorry, das ich das erst verschwiegen hatte. Für mich war meine Funktion schon so selbstverständlich geworden das ich nicht mehr an den Unterschied in der Rückgabe
De Funktion hatte ich mal vor ein paar Jahren bei meinem Kunden geschrieben, als dort nach dem Einbau neuer schneller Server kaum noch eine Db-Funktion sauber lief. Ich weiß nicht ob das noch DBFNTX oder schon FOXCDX war. Auf jeden Fall gab es plötzlich stapelweise Laufzeitfehler und Datenmurks. Nachdem ich dann die relevanten Funktionen (DbSkip, DbAppend, DbRLock, DbRUnLock, DbClose, DbSeek) auf solch ein Muster umgeschrieben hab, lief alles wieder sauber und stabil.
Jan