|
|
|
Forum Member
      
Group: Forum Members
Last Login: Yesterday @ 08:46:25
Posts: 36,
Visits: 636
|
|
Hi all,
It's always been irritating me that all Undo/Redo blocks are cleared after updating the DB. It means that a user can't efficiently use Undo/Redo functionality along with frequent updates to the DB. It's especially bad in a multi-user environment when Update DB operation is done to sync data.
However I found that Update DB operation can work independently of the Undo/Redo operations with a couple of tricks applied. First trick is to disable the clearing of Undo blocks on update (see the protectUndoBlocksFromClearingInUpdate() method in the example code). Second trick is to modify the objects' state after Undo/Redo operations to properly make them dirty (see the correctObjectsState(...) method).
Download the example here: http://olegzhukov.com/UndoAfterUpdate.zip
Question to Jonas and Hans: do you (dis)approve such method? Any shortcomings from your perspective?
The provided solution seems to be stable. So everyone is welcome to download it and try it out. In the example I use the embedded Firebird server (dll's included).
--
Oleg Zhukov
|
|
|
|
|
Supreme Being
      
Group: Forum Members
Last Login: 2011-07-14 17:05:00
Posts: 290,
Visits: 2 617
|
|
So, you create some undo blocks, update the DB, undo the blocks, and then update the DB again. So you are updating newer objects in the DB with older ones.
What's worse is that any new objects which have been created in the DB in your update will not be deleted on the 2nd update, and any objects which were deleted in the first update will not be undeleted in the 2nd.
I think you need to question your requirement
====
Pete
|
|
|
|
|
Forum Member
      
Group: Forum Members
Last Login: Yesterday @ 08:46:25
Posts: 36,
Visits: 636
|
|
Hi Pete,
So, you create some undo blocks, update the DB, undo the blocks, and then update the DB again. So you are updating newer objects in the DB with older ones.
Well, "old" and "new" notion is not quite applicable here. Imagine I changed a person name from "Peter" to "Pete" then updated the DB. Then I decided that it should be "Peter", undone changes and updated DB again. It's rather feasible scenario.
What's worse is that any new objects which have been created in the DB in your update will not be deleted on the 2nd update, and any objects which were deleted in the first update will not be undeleted in the 2nd.
They will be That's what the state correction is done for. No primary key violation or whatever else occured so far.
--
Oleg Zhukov
|
|
|
|
|
Supreme Being
      
Group: Forum Members
Last Login: 2011-07-14 17:05:00
Posts: 290,
Visits: 2 617
|
|
They will be  That's what the state correction is done for. No primary key violation or whatever else occured so far.
You will undo deletes and undo new objects too? What about updates made to other objects by other users which have been based on the changes you made?
1: You change an object state and update the DB.
2: I create new objects based on the state of some objects, including the one you updated (e.g. Status = ready for delivery)
3: You undo the change and update the DB.
Now we have a scenario where a "scheduled delivery" has been created on an object with a status "Ready for delivery" but you have reverted the status to "Not read for delivery" - a transition which according to its state machine cannot occur.
====
Pete
|
|
|
|
|
Forum Member
      
Group: Forum Members
Last Login: Yesterday @ 08:46:25
Posts: 36,
Visits: 636
|
|
Now we have a scenario where a "scheduled delivery" has been created on an object with a status "Ready for delivery" but you have reverted the status to "Not read for delivery" - a transition which according to its state machine cannot occur.
Well, you've chosen an example where a user cannot revert his changes other than by undoing changes (since reverse state machine transition is not allowed in your example). But generally the problem is broader: what if user A has done some changes, then user B made some worked based on these changes, then user A has cancelled his changes (either by "Undo" operation or manually changing state back to the initial value). As a result the work done by B is in vain or even harmful (at worst case). So such conceptual problem applies to any kind of collaboration, not to specific Undo mechanism issues. But...
... But you've directed me to thinking of some technical problems that can arise. For example:
1) User A unlinks object X from object Y. Updates DB
2) User B deletes object Y. Updates DB
3) User A undoes his change. ECO will throw exeption trying to link again X to deleted Y.
To the moment I haven't come up with something better than swallowing such exceptions...
--
Oleg Zhukov
|
|
|
|
|
Supreme Being
      
Group: Forum Members
Last Login: 2012-02-01 10:36:37
Posts: 101,
Visits: 751
|
|
OZh (2010-04-08)
1) User A unlinks object X from object Y. Updates DB
2) User B deletes object Y. Updates DB
3) User A undoes his change. ECO will throw exeption trying to link again X to deleted Y.
To the moment I haven't come up with something better than swallowing such exceptions...
You cannot ensure that given a list of actions (change sets) - {A1, A2} action A1 can be "undone" without first undoing A2. Don't swallow the exception - at least let the user know they cannot undo step 1).
Rethink what problem you want to solve and think of another (better) design to solve it.
/Pawel
|
|
|
|
|
Forum Member
      
Group: Forum Members
Last Login: Yesterday @ 08:46:25
Posts: 36,
Visits: 636
|
|
Pawel (2010-04-08)
You cannot ensure that given a list of actions (change sets) - {A1, A2} action A1 can be "undone" without first undoing A2. Don't swallow the exception - at least let the user know they cannot undo step 1).
Yes, it's an option to prohibit "Undo" operations if any collisions between A1 and A2 are found. But optimistic swallowing of exceptions is a possible behavior too (why not?). Which one approach to use - it depends on user requirements.
Rethink what problem you want to solve and think of another (better) design to solve it.
One of main user requirements is to send changes to DB and other users (so that user B can immediately see what user A has done) while allowing to undo these changes.
Another less imporant requirement is to allow other users not only track changes but also modify objects together. That's where collisions and exceptions may occur.
Regards,
--
Oleg Zhukov
|
|
|
|
|
Supreme Being
      
Group: Administrators
Last Login: 2010-11-30 12:17:13
Posts: 1 230,
Visits: 1 382
|
|
I haven't looked closely at the implementation, but I can imagine problems in the following areas:
* Optimistic locking
* Consistency of bidirectional links
* Possibly synchandler messages
* Create/Delete-operations
If you delete an object, save the deletion and then undo the deletion, will the object be marked as "new" so that it is inserted on next update? Will it get the same primary key?
/Jonas Hogstrom [CapableObjects]
|
|
|
|
|
Supreme Being
      
Group: Forum Members
Last Login: 2011-07-14 17:05:00
Posts: 290,
Visits: 2 617
|
|
What you seem to need is an application command/response layer which works on commands, stores those demands in a db, and allows you to undo them. Your use of IUndoService is incorrect imo.
====
Pete
|
|
|
|