Author | Topic: Problems with dbregisterclient() function | |
---|---|---|
Milorad Milivoj+¬a | Problems with dbregisterclient() function on Wed, 25 Jul 2018 20:00:41 +0200 Hallo, colleagues. I am using Xb++ 1.90, in character mode, DBFCDX drivers. I want to introduce automatic timestamp creating to every record of every table of my database, for append, replace and delete events. I find that dbregisterclient() function can do much for me. For every table that my application open, I create an object variable from class with :Notify() method, and register current work area with that variable. My idea was to update timestamp columns in :Notify() method, based on events "append", "update" and "delete". But, problems arised. = Problem 1 When deleting a record, :Notify() event did fired with "update" event, not with "delete" event. OK, I understand it, because DBF driver do not remove record from table, just mark it for deletion (marking is more like "updating"). That was not big problem - I agreed that deleting is just specific "updating". = Problem 2 When deleting record, deleted record was not publicly visible as "deleted" before current record pointer move to another record, so as consequence, :Notify() method was not arised before skipping to other record. OK, I skip to next record, than return to original record, write timestamp and finish task. But, in meantime - immediately after skip, :Notify() method do something "ingenious" - it delete BOTH records, and make second (auxiliary) record EXACTLY SAME as main record, just as it would be if I copy every column value from first to second record! I spent 3 days to investigate what happends, and finaly make a solution - write one more function level, where program remember what have to be done and - when main record became visible as deleted - go to it and update timestamp. = Problem 3 At very start of program, I have this situation: - open two very small tables - lock both tables with file locks - make changes to both of them (appending some records and updating others) - unlock both tables - close both tables with dbclosearea() function After succesfuly finishing all tasks (except last), program fails with error message "Lock is required for this operation" with error "operation" property value equal "dbclosearea". Why any lock would be needed for closing table? OK, with memory buffers in mind, I then put COMMIT before closing tables, but with no changes. When I block-out that program segment, same happends at first next unlockall() function call, with exact same error message! Xbase tells me that I need to lock table when I want to unlock it!!! For check myself, then I just blocked new idea with opposite preprocessor directive, and every operations works well, just as for years before. I spent more than a week for this problem, and can not go any step behind it! On the other hand, I don't want to throw-out this improvement. Who have deeper experience with dbregisterclient() function? Any suggestion can make great change. Thanks in advance. Milorad | |
Jim Lee | Re: Problems with dbregisterclient() function on Wed, 25 Jul 2018 21:34:58 +0200 hi, show us your Notify Methode you got DBO_MOVE_PROLOG before move and DBO_MOVE_DONE when ready so where do you have DBO_TABLE_UPDATE DBO_TABLE_DELETED DBO_TABLE_APPEND : | |
Milorad Milivoj+¬a | Re: Problems with dbregisterclient() function on Sat, 28 Jul 2018 11:24:16 +0200 Thank you for your answer, Jim. I confess that I did not even look at events you mention. One of the clearest versions of my :Notify() event follows: METHOD SinhroLog:Notify(tnEvent, mp1, mp2) local lcOldAlias:=alias(), llWriteDone:=.T. if tnEvent <> xbeDBO_Notify return ( self ) endif dbselectarea(::cAlias) DbSuspendNotifications() while .t. do case case mp1 == DBO_TABLE_APPEND if fieldpos( ::cAlias+'_CTIME' ) > 0 update date/time column for "Creating" record fieldput(fieldpos(::cAlias+'_CTIME'), SetUpdTime()) endif case mp1 == DBO_TABLE_UPDATE if fieldpos( ::cAlias+'_UTIME' ) > 0 update date/time column for "Updating" record fieldput(fieldpos(::cAlias+'_UTIME'), SetUpdTime()) endif case mp1 == DBO_TABLE_DELETED if fieldpos( ::cAlias+'_UTIME' ) > 0 update date/time column for "Updating" record fieldput(fieldpos(::cAlias+'_UTIME'), SetUpdTime()) endif otherwise non-writable events llWriteDone := NE endcase if llWriteDone set some object variables ... ... endif exit enddo DbResumeNotifications() if not empty(lcOldAlias) dbselectarea(lcOldAlias) endif RETURN ( self ) Milorad Jim Lee wrote in message news:735fad77$1285bd31$3d3c@news.alaska-software.com... >hi, > >show us your Notify Methode > >you got DBO_MOVE_PROLOG before move and DBO_MOVE_DONE when ready > >so where do you have >DBO_TABLE_UPDATE >DBO_TABLE_DELETED >DBO_TABLE_APPEND >: |