Unexpected behavior during BO Save-on-Transaction


Author
Message
Kirk M Sherhart
Kirk M Sherhart
StrataFrame Novice (95 reputation)StrataFrame Novice (95 reputation)StrataFrame Novice (95 reputation)StrataFrame Novice (95 reputation)StrataFrame Novice (95 reputation)StrataFrame Novice (95 reputation)StrataFrame Novice (95 reputation)StrataFrame Novice (95 reputation)StrataFrame Novice (95 reputation)
Group: Forum Members
Posts: 41, Visits: 259
I've come across some unexpected behavior when using bo.Save(true) (i.e. BO-level saving, not form-level saving)

If I have a simple saving method as follows:

void SaveProject() {
    BusinessLayer.TransactionBegin("", IsolationLevel.ReadCommitted);
    SaveUndoResult result = bo.Save(true);
    if (result == SaveUndoResult.Success) {
        BusinessLayer.TransactionCommit("");
    }
    else {
        BusinessLayer.TransactionRollback("");
    }
}


Let's suppose I call SaveProject(), but the bo fails its CheckRules.  Therefore, the save operation fails and the transaction is rolled-back, as expected.  However, the internal value of bo._IsSavedOnTransaction is set to true by bo.Save function, even though the rules checked fail. (Note: the call to BusinessLayer.TransactionRollback does not reset the value bo._IsSavedOnTransaction to false.)

Now, if I fix the cause of the rule failure and call ProjectSave() a second time, nothing happensAngry Why? Because the value bo._IsSavedOnTransaction is true from the first call, and bo.IsDirty (called in the bo.Save() routine) returns false.  Therefore, no save is attempted.

I don't know if this is a bug or a feature.  At least, it's unexpected behavior.
Replies
StrataFrame Team
S
StrataFrame Developer (6.5K reputation)StrataFrame Developer (6.5K reputation)StrataFrame Developer (6.5K reputation)StrataFrame Developer (6.5K reputation)StrataFrame Developer (6.5K reputation)StrataFrame Developer (6.5K reputation)StrataFrame Developer (6.5K reputation)StrataFrame Developer (6.5K reputation)StrataFrame Developer (6.5K reputation)
Group: StrataFrame Developers
Posts: 3K, Visits: 2.5K
You're right, guys, that's a bug.  I've never run into it before because we always use the TransactionCommit() and TransactionRollback() calls within a Try/Catch.  If the TransactionCommit() throws an exception, then the TransactionRollback() is called to clean up any records that failed to insert together.

Inside the TransactionCommit() method, there is a call to ResetIsSavedOnTransactionFlagOnBusinessObjects() which resets that flag you're talking about.  Since we always call TransactionCommit() and then only call TransactionRollback() in the Catch block, we've never run into your issue.  

In case you're wondering, the _IsSavedOnTransaction flag is used to prevent multiple saves on business objects when you save on a transaction.  The scenario this prevents goes like this:

1) Business object A is the parent
2) Business object B is the child
3) You call Save() on A, but since it's saved on a transaction, the AcceptChanges() is not called on the table until the commit, so it stays dirty, even though the records have been inserted/updated/deleted.
4) You call Save() on B, which checks to make sure it's parent has been saved first, which it has, but without the _IsSavedOnTransaction flag, the child thinks the parent is still dirty, so it gets saved again

I have modified the TransactionRollback() root overload as follows to reset the _IsSavedOnTransaction flag for those of you who like to call TransactionRollback() without first calling TransactionCommit().



        ''' <summary>
        ''' Rolls back the transaction that is tied to all business objects associated with the given database
        ''' (All business objects that have the same database name use the same transaction.)
        ''' </summary>
        Public Shared Sub TransactionRollback(ByVal DataSourceKey As String, ByVal TransactionKey As String)
            '-- 4/10/2012 - Ben
            '-- Added this call to reset the flag on the business objects so they can remain dirty after 
            '   the transaction is rolled back without a call to TransactionCommit() first
            ResetIsSavedOnTransactionFlagOnBusinessObjects(DataSourceKey, TransactionKey)
            '-- http://forum.strataframe.net/Topic30915.aspx

            DataLayer.TransactionRollback(DataSourceKey, TransactionKey)
        End Sub

The code starts on line 6250 in the BusinessLayer.vb file.  You can modify it yourself and recompile.  If you don't want to do that, you're other options would be to wait for the next build, or *hushed voice* call ResetIsSavedOnTransactionFlagOnBusinessObjects() through reflection */hushed voice*.

Hope that helps, and thanks for the catch.

Ben 
Edited 13 Years Ago by Ben Chase
Edhy Rijo
E
StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)StrataFrame VIP (6.4K reputation)
Group: StrataFrame Users
Posts: 2.4K, Visits: 23K
Hi Ben,
Welcome back!!!! Tongue

Thanks for the explanation, I am sure Larry will try to implement the change.  In my case I use transactions the same way you do and never hit that issue.

Edhy Rijo

GO

Merge Selected

Merge into selected topic...



Merge into merge target...



Merge into a specific topic ID...





Similar Topics

Reading This Topic

Login

Explore
Messages
Mentions
Search