ApplyEdit() and Undo from Failed Save?

ApplyEdit() and Undo from Failed Save?

Old forum URL: forums.lhotka.net/forums/t/4339.aspx


JohnB posted on Tuesday, February 12, 2008

I am having an issue and would like to get some feedback on what I am trying to do here.

Just for the record I am working with an ERLB but this issue applies to any of the base classes in the Csla framework.

I have my code setup in a similar manner to what Rocky has for PT. Everything works great but I am having issues when an error occurs during the Save operation. I've taken a snapshot of some PT code to demonstrate my issue:

Private Sub RebindUI(ByVal saveObject As Boolean, ByVal rebind As Boolean)

  ' disable events
  Me.ProjectBindingSource.RaiseListChangedEvents = False
  Try
    ' unbind the UI
    UnbindBindingSource(Me.ProjectBindingSource, saveObject, True)

    ' save or cancel changes
    If saveObject Then
      mProject.ApplyEdit()
      Try
        Dim temp As Project = mProject.Clone()
        mProject = temp.Save()

      Catch ex As Csla.DataPortalException
        '-- MessageBox.Show(ex.BusinessException.ToString() .....

      Catch ex As Exception
        '-- MessageBox.Show(ex.ToString() .....

      End Try
    Else
      mProject.CancelEdit()
    End If

  Finally
        ' rebind UI if requested
    If rebind Then
      BindUI()
    End If
    
    ' restore events
    Me.ProjectBindingSource.RaiseListChangedEvents = True
    
    If rebind Then
      ' refresh the UI if rebinding
      Me.ProjectBindingSource.ResetBindings(False)
    End If
  End Try

End Sub



Standard code and works great but let's say that my temp.Save() fails. Sure I get back my cloned object but ApplyEdit was already called. My object that I have is no longer in a state in which I can cancel my changes. Once I display the error to the user I cannot "undo" what the user attempted to save. Am I missing something?

rsbaker0 replied on Tuesday, February 12, 2008

We're facing this same issue.

I think you are correct in that "undo" is no longer specifically an option, but I think I'm going to expose the capability to simply refetch the object from the database, which is also a form of "undo".

ajj3085 replied on Wednesday, February 13, 2008

You can do your clone before calling ApplyEdit.

JohnB replied on Wednesday, February 13, 2008

ajj3085:
You can do your clone before calling ApplyEdit.


I tried this before I posted and it worked but I am hesitant to use this as a solution because according to Rocky's book, as well as his post, we are supposed to model our saving/binding like he has with the PT application.

My overall concern is databinding and if this change will cause any other issues.

Thanks,
John

JohnB replied on Wednesday, February 13, 2008

I wanted to provide an update to this issue. We've done several tests and have not had any issues so far. It would be nice to know if there is anyone else who is doing something similar....cloning before calling ApplyEdit.

ajj3085 replied on Thursday, February 14, 2008

Its come up before.  I'm not sure what the "offical" stance is though, but it does seem to work.  IIRC, the cloning will keep the BindingEdit variable true, so rebinding the object to the UI will ignore the BeginEdit call again, so the edit level should remain unaffect... IIRC.

RockfordLhotka replied on Thursday, February 14, 2008

As far as I know this should be a fine thing to do as long as it doesn't confuse data binding - which your testing indicates is OK. My only worry would be that if the user can interact with the UI in the middle (after you clone, before you rebind) they could change the currency within data binding by clicking on a different row in a grid or whatever. That'd royally mess things up because the object and data binding would be out of sync. But I would think that you are fine as long as that scenario can't occur.

dagware replied on Wednesday, February 25, 2009

Just a follow-up on this thread. This is for CSLA 3.0.5, not sure how it affects other versions:

The above advice to call ApplyEdit() on the clone instead of the original object, when doing a save, works well.

However, if you get an error while saving, and then you rebind to the original object, DO NOT let BindUI() call BeginEdit() again. Otherwise you will have to call CancelEdit() more than once.

I would have modified BindUI() to check the object's EditLevel, but that property isn't a public property. So instead, I added a bool parameter to BindUI() called "doBeginEdit", and I pass the appropriate value depending on whether the object is being re-bound because of an error.

It took me a while to figure this out, so I thought I'd post it just in case someone else has the same issues.

Dan

Copyright (c) Marimer LLC