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?
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?
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()
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.
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.
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).
Thanks Rocky for clarifying the distinctions when IsDirty is set..
Copyright (c) Marimer LLC