This has been discussed on the forum a few times in the past.
If you don't like the behavior, you can turn it off - reverting to the old (broken) behavior.
The reason the old behavior was broken, is that it relied on the UI developer to do the clone themselves, to properly handle the case that an exception occurred during the save. Of course almost nobody write correct UI code (yours is a good example).
The problem is that a save operation alters the state of the object graph. The metastate is altered (IsDirty, IsNew, etc) and often the database generates new primary keys and timestamps. If the save fails half-way through, the database rolls back due to your use of transactions. But the object graph is left in an indeterminate and broken state.
So the UI code has to wrap all Save operations in a try..catch and either do a clone before the save, or re-fetch the entire object graph in the case of an exception.
Since virtually nobody was doing the right thing, it was a source of constant pain for people using the framework. Additionally, when I implemented ERLB, CslaDataProvider and other objects that do saves for you, I had to constantly replicate the correct behavior - which was just wrong.
So I fixed the problem at the source - in the data portal - so it does the right thing.
But if you want the broken behavior, you can revert to it. I just recommend wrapping all your save calls in try..catch blocks so at least your app isn't broken.
On the other hand, if you do leave the autoclone enabled (which I recommend), then your typical save code should be like this:
o = o.Save();
and even that should be in a try..catch block, because you can still get exceptions of course, and you should report them to the user appropriately.
Copyright (c) Marimer LLC