I need advise about restoring original object after Saving failed. Here is what I am doing:
I use ViewModelBase for my WPF application with ManageObjectLifetime set to false, since I want to control it myself.
1. "Edit" button pressed, I call ISupportUndo.BeginEdit. Object considered to be in edit mode. EditLevel = 1
2. Save button called
ISupportUndo.ApplyEdit called. Suppose all rules are fine, EditLevel = 0
I call BeginSave from the base class, When saving into the database Unique Index exception is thrown
3. I handle OnError and OnSaved, proper error message is shown, Model is not changed. But I am no longer in "Edit" mode. My EditLevel is 0, I cannot Press Cancel and restore to original values as I could before pressing Save.
What I want to have is the same state as before pressing Save button.
I can try to save object clone before pressing Save, but it looks like hack. What would be more elegant solution?
I tried to search for the answer but all I could find is this: http://forums.lhotka.net/forums/p/6103/29610.aspx. And there is no solution there.
If you want the Cancel button to work so the user can cancel after an exception during save, you will need to take a clone of the object graph before calling ApplyEdit.
ApplyEdit tells the graph that you are done - it commits all changes in memory. There is no cancel after that point.
So if you want to cancel, you need to have a copy of the graph from before the ApplyEdit.
Thank you for such quick reply. Will do that. I don't want user to see the difference between errors from validation rules, exception on the client or exceptions on the server.
I did what was advised and now I seems to have a problem with this with some very specific sequence of events. I am using ViewModel from Csla.Xaml
-- Edit button pressed
1. Begin Edit is called
2. Data modified the way some rules are broken
--- User presses Save button
3. Clone is created using IClonable.GetClone method
4. ApplyEdit is called
5. Begin Save is called which results in Error
6. Model is set to previously saved Clone
-- User presses Cancel button
7. CancelEdit is called
-- Edit button pressed
8. Begin Edit is called again
9. Object is modified to have rules broken again
-- User presses Save button
10. Clone is created
And here we have interesting thing. In this new clone, BusinessRules.Target is incorrect. It looks that's another duplicate instance of an object is created and BusinessRules.Target points to it.
I would appreciate if you point into any direction. I am going to create stripped down example with dummy object to duplicate it.
I found my problem. Please disregard my question.
Would you mind sharing what the problem and solution was? Maybe it could help others.
Sure,
I didn't get to the very bottom of it, but generally, we had some non-CSLA class as part of our business object. In this class we were not careful about serialization. The biggest issue was that this class referenced our business object and our object referenced this class, and these references were not marked as [NonSerializable].
At this moment I just commented few things out, we are going to address it little bit later. But I believe having these references created "shadow" copy of our business object during "CancelEdit" operation. And then, we the clone was created, business rules switched to this shadow copy. As I said it required very specific steps to reproduce to get to this problem.
1. BeginEdit
2.GetClone
3.Clone.CancelEdit
4.CloneBeginEdit
5.GetClone from first Clone
And only on this second clone we have the problem. Not earlier, not until CancelEdit involved.
Copyright (c) Marimer LLC