Clarification on when IsDirty is set

Clarification on when IsDirty is set

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


GregBen posted on Monday, July 26, 2010

I thought IsDirty is set when a property changes in an object, when using managed properties.  Isn't the following a valid managed property definition?  The string `Confidential (C, N or D)` is my friendly name.

    Private Shared ConfidentialProperty As PropertyInfo(Of String) = RegisterProperty(New PropertyInfo(Of String)("Confidential", "Confidential (C, N or D)"))
    Public Property Confidential() As String
        Get
            Return GetProperty(ConfidentialProperty)
        End Get
        Set(ByVal value As String)
            SetProperty(ConfidentialProperty, value)
            'LoadProperty(ConfidentialProperty, value)  ' I thought this might force IsDirty, but doesn't
        End Set
    End Property

 

I use the following business rule to determine the value for the Confidential member.

Private Shared Function CheckSpecialDocket(Of T As Class)(ByVal target As DocketEdit, ByVal e As Validation.RuleArgs) As Boolean
        Dim exists As Boolean
        Dim val As String = target.Confidential

        exists = DocketIsSpecCodeCMD.Execute(target.DocketCode)    ' run Command to check lookup table
        Using target.BypassPropertyChecks
            If exists Then
                target.Confidential = "Y"
            Else
                target.Confidential = "N"
            End If
            ' If new value isn't the same as the original value, mark item as dirty
            If Not val = target.Confidential Then target.MarkDirty()
        End Using

        Return True

    End Function

It would seem once I change the Confidential value, the object DocketEdit should be marked as IsDirty.  However, I need to compare the new value with the original value, and manually call MarkDirty, which seems unnecessary.  Am I missing something?

 

RockfordLhotka replied on Monday, July 26, 2010

SetProperty() should mark the object as dirty - assuming the new property value is different from the previous value.

If you put a breakpoint on your "If Not val ..." line of code and check target.IsDirty you are saying it is false?

GregBen replied on Monday, July 26, 2010

Here are the results of my watch list within the business rule`CheckSpecialDocket`.

        val    "e"    String
        target.IsDirty    False    Boolean
        target.Confidential    "Y"    String

The DB field had the value of `e` before running the process, the rule changed it to `Y`, and IsDirty is still false (breakpoint on the line

If Not val = target.Confidential Then target.MarkDirty()

RockfordLhotka replied on Monday, July 26, 2010

Then I'd suggest doing a "Step Into" the target.Confidential = "Y" statement to see where it goes.

SetProperty() is pretty straightforward - it follows the flowchart in the Expert 2008 Business Objects book - and if the old and new values are different it'll call MarkDirty().

Another thing you could do is override MarkDirty() in your class and put a breakpoint there.

But something very odd is clearly happening, and the only thing you can do is spend some quality time with the debugger to figure out what.

GregBen replied on Wednesday, July 28, 2010

When I modify LineItemEdit.Child_Fetch in Demo3 as follows, IsDirty never becomes true, even when changed in ToUpper.   This is exactly the behavior I see in my solution, when validating data.

    private void Child_Fetch(SafeDataReader dr)
    {
      using (BypassPropertyChecks)
      {
        Id = dr.GetInt32("Id");
        ProductId = dr.GetString("ProductId").ToLower();
        Price = dr.GetDouble("Price");
        Quantity = dr.GetInt32("Quantity");
        Details = DataPortal.FetchChild<Details>(Id);
      }

   ValidationRules.CheckRules(); // This runs the rules, updates the value, but doesn't set IsDirty=true.

    }

My solution sets values like this: LoadProperty(ConfidentialProperty, dr("Confidential"))

When I remove BypassPropertyChecks in Child_Fetch, and change LoadProperty to SetProperty, the object is marked as dirty as soon as a business rule is run, and the property value is updated as required in the rule.  However, the object is now ALWAYS marked as dirty, even if the rule doesn't update the value.  Maybe that is just the way CSLA works?  However, it seems pointless to update a database with data that hasn't changed.

>> Another thing you could do is override MarkDirty() in your class and put a breakpoint there.

In version 3.8.1 of CSLA, MarkDirty isn't overridable

Protected Sub MarkDirty()
     Member of Csla.Core.BusinessBase
Summary:
Marks an object as being dirty, or changed. 

 

RockfordLhotka replied on Wednesday, July 28, 2010

The following are intentional ways CSLA works:

Finally, in some versions of CSLA MarkClean() (actually MarkOld()) was called after DataPortal_Fetch() by the data portal, so it was essentially impossible for DataPortal_Fetch() to leave the object in a dirty state.

I don't remember exactly when this was changed, but in current versions of the framework MarkOld() is invoked before DataPortal_Fetch() - so it is now possible for DataPortal_Fetch() to leave the object as dirty (though that's usually undesirable).

GregBen replied on Friday, July 30, 2010

Thanks Rocky for clarifying the distinctions when IsDirty is set..

Copyright (c) Marimer LLC