Maybe this is a dumb observation, but I think that there should be an Undelete method that sets mIsDeleted = False for EditableRoot BO's
If I have a "Delete" button in my UI that calls Delete, but fails when saving:
MyBO.Delete() ' Mark the BO as deleted
MyBO.Save() ' Save fails and throws an exception (for ex: Server unavailable)
Then the server is back again but the user changes its mind, updates the BO and press the "Save" button... the BO gets deleted instead of updated! (because is still marked for deferred deletion). Ideally I'd like to do this:
Try
MyBO.Delete()
MyBO.Save()
Catch ex As Exception
MyBO.Undelete()
End Try
The Undelete sub is very easy to implement but I think it should be included in the Framework. What do you think ?
Regards
Jacobo
The automatic cloning of the framework doesn't solve the problem because it would clone the object that is already marked for deletion, so the original one has IsDeleted = True.
If I clone it manually before calling .Delete() then I would incur in the overhead of two clonings wich is undesirable. I would have to turn off automatic cloning wich is undesirable too.
No, BeginEdit/CancelEdit is the usual with Child objects but the framework disallows saving of Root objects with EditLevel > 0, see this snippet from BusinessBase.Save :
If EditLevel > 0 Then
Throw New Validation.ValidationException( _
My.Resources.NoSaveEditingException)
End If
So with your suggested approach, BeginEdit would set EditLevel = 1, the clone would have EditLevel = 1 too and Save would fail with NoSaveEditingException
No, as I said before I'd like to use the "automatic cloning on save" feature provided with the framework so if I clone the object manually as you suggests I would incur on two clonings (the fw would clone the object again) wich is undesirable. This setting is global and I'd prefer to not turn it off.
As for the use case, for ex, think on an user who try to delete an object but hasn't enough permissions so he gets an error. After seeing the problem, he wants to update a status field to "disabled" or at least write in a memo field "this must be deleted by admin". But pressing "save" throws the same "not enough permission to delete" error again and again because the BO still has IsDeleted = True.
My thinking is that if the framework provides a method to allow the BO user to mark an Editable root object as deleted, it should provide a method to clear this flag if the BO user repents of this action.
Thanks for discussing this!
Regards
amselem:No, as I said before I'd like to use the "automatic cloning on save" feature provided with the framework so if I clone the object manually as you suggests I would incur on two clonings (the fw would clone the object again) wich is undesirable. This setting is global and I'd prefer to not turn it off.
amselem:As for the use case, for ex, think on an user who try to delete an object but hasn't enough permissions so he gets an error.
Your UI should be preventing this by checking CanDelete, or maybe even CanExecuteMethod (if you need per instance authorization).
amselem:After seeing the problem, he wants to update a status field to "disabled" or at least write in a memo field "this must be deleted by admin". But pressing "save" throws the same "not enough permission to delete" error again and again because the BO still has IsDeleted = True.
Again, if your UI prevents the user from marking delete (because your BO should be able to answer that question) then this won't be an issue. Also, the cloning before calling ApplyEdit will fix this issue as well, but you shouldn't need it if your UI correctly prevents Delete from being called.
amselem:My thinking is that if the framework provides a method to allow the BO user to mark an Editable root object as deleted, it should provide a method to clear this flag if the BO user repents of this action.
Well, it does, just not after the user has also indicated they are done editing the object and attempts to save it. What you're asking is to be able to continue editing an object which is now in an invalid state. I don't think that's a good idea.
Thanks for your comments ajj3085,
ajj3085:Well, I think that's the best way to proceed, even if you have two clones.
Yes currently I'm using the two cloning approach and it performs well in my use case.
All this thinking came because it seemed to me a little weird to clone the object before saving when csla is doing it automatically for me. So that thinking lead me to determine that the Business Object user should manage IsDeleted as any other state variable of the BO. In fact I usually create rules involving IsDeleted (for disabling the rule when deleting), so changing the IsDeleted value as many times as the BO User wants would never leave the BO in an invalid state.
ajj3085:
Your database access will take more time than any cloning, so unless your object graph is pretty large your user shouldn't notice any slowdown.
Well, maybe my examples weren't the best for showing what I wanted, think that Save can throws an exception withouth touching the database, for ex. if the BO has broken rules and is not valid, save would fail.
ajj3085:Your UI should be preventing this by checking CanDelete, or maybe even CanExecuteMethod (if you need per instance authorization).
ajj3085:Again, if your UI prevents the user from marking delete (because your BO should be able to answer that question) then this won't be an issue. Also, the cloning before calling ApplyEdit will fix this issue as well, but you shouldn't need it if your UI correctly prevents Delete from being called.
When I talk about "BO user" I mean "UI programmer" not "application end-user". So maybe is under my control that he can guide the end-user using UI elements (like enabling/disabling the save button) or maybe not, maybe he forgot to implement it or maybe there wasn't time to do it. Me, as a BO developer, I don't like to rely on the UI and I prefer to do checkings and throw exceptions where has sense.
ajj3085:Well, it does, just not after the user has also indicated they are done editing the object and attempts to save it. What you're asking is to be able to continue editing an object which is now in an invalid state. I don't think that's a good idea.
"it seems very simple to create an Undelete sub. "
It seems like you have given this a lot of thought.
So why not just create the Undelete Sub in your Base class that inherits from CSLA and which all your BOs inherit from?
Or perhaps you did already and are suggesting this so Rocky can consider adding it to the framework?
Joe
Well I couldn't create the sub in my Base class because mIsDeleted is private, and there isn't anything like MarkUndeleted. I'm currently solving this issue cloning manually the BO before saving (in addition to the csla "clone before save" feature).
I was not suggesting to Rocky to add the sub, it's just that when I found this issue I went to see if there was anything supporting the undeletion of root objects, but I didn't find anyhing in the framework nor the forum. So I didn't know if my approach was incorrect or there is a good reason for not undeleting EROs.
Of course I'd be glad if Rocky consider this sub is worth enough to add it to the framework.
Hi Andy,
I like a lot your idea of making CSLA's classes as partial classes. I also have my source under version control but I was changing the framework code when needed a hack or something like this. Then on each upgrade I was using winmerge to keep my changes, a manual and error prone task. Thanks for your comments!
Copyright (c) Marimer LLC