Entity is marked as dirty incorrectly

Posts   
 
    
Posts: 254
Joined: 16-Nov-2006
# Posted on: 11-May-2008 20:02:01   

Version 2.5.08.0328

I have a DefectEntity which has a DefectSeverityEntity. If I save the entity, then reload and set the DefectSeverity property again to the same instance its flagged as dirty.

defect.DefectSeverity = severitiesComboBox.SelectedItem as DefectSeverityEntity;
daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 12-May-2008 06:59:43   

Hi Matt,

Please post the save code snippet. Are you saving recursively? How did you realize the property is dirty (debugging, exception, etc.)? I assume you are using SelfServicing, isn't?

David Elizondo | LLBLGen Support Team
Posts: 254
Joined: 16-Nov-2006
# Posted on: 12-May-2008 10:19:37   

Sure I actually used the method below to determine whether the entity is dirty for some logic to determine whether the user actually made any changes.

If you save defect.Save(true) some database activity causes the supposed changes to be saved.

        /// <summary>
        /// Determine whether the entity or any of it's contained inner 
        /// entities are dirty.
        /// </summary>
        /// <param name="entity">The entity to check</param>
        /// <returns></returns>
        public static Boolean IsEntityOrInnerEntityDirty(IEntity entity)
        {
            Boolean entityDirty = false;

            ObjectGraphUtils utils = new ObjectGraphUtils();
            List<IEntity> list = utils.ProduceTopologyOrderedList(entity);
            foreach (IEntity innerEntity in list)
            {
                if (innerEntity.IsDirty)
                {
                    entityDirty = true;
                    break; // for
                }
            }

            if (entityDirty)
            {
                TraceDirtyEntity(entity);
            }

            return entityDirty;
        }

        /// <summary>
        /// Traces and output all entities and any of it's contained inner 
        /// entities which are dirty.
        /// </summary>
        /// <param name="entity">The entity to check</param>
        /// <returns></returns>
        public static void TraceDirtyEntity(IEntity entity)
        {
            Trace.WriteLine("Tracing dirty entities");
            Trace.Indent();

            ObjectGraphUtils utils = new ObjectGraphUtils();
            List<IEntity> list = utils.ProduceTopologyOrderedList(entity);
            foreach (IEntity innerEntity in list)
            {
                if (innerEntity.IsDirty)
                {
                    Trace.WriteLine("Entity name " + innerEntity.LLBLGenProEntityName + " is dirty");
                }
            }

            Trace.Unindent();
        }
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 12-May-2008 11:58:42   

It shouldn't mark it as dirty if the values are the same. It DOES unattach and re-attach the related entity again, but this should lead to the same situation (this is changed in v2.6).

Which field is actually marked as changed? If it's the FK field, which shouldn't occur if the fk field has the same value already. (which should be the case if you set it to the same severity entity)

Frans Bouma | Lead developer LLBLGen Pro
Posts: 254
Joined: 16-Nov-2006
# Posted on: 12-May-2008 20:16:19   

The DefectEntity is reported in the trace message as being changed.

Are there any trace switches you want me to enable and capture or do you want me to add any code before / after the property is set to help diagnose this further?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 12-May-2008 21:21:24   

MattAdamson wrote:

The DefectEntity is reported in the trace message as being changed.

No, that's an entity. I meant the FIELD in the entity. If an entity is marked dirty, a FIELD is marked changed. Please check which field that is. Then you can check before/after assigning the related entity the second time (i.e. after the fetch) if the value BEFORE the assignment is indeed different.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 254
Joined: 16-Nov-2006
# Posted on: 12-May-2008 21:48:55   

The value is the same before and after the assignment however I did enable all LLBLGEN trace settings on full verbose mode and got the following output on just the setting of the DefectSeverity property

Method Enter: CollectionCore.PerformAdd
Entity to Add Description:
Entity: CodeReviewer.EntityClasses.DefectEntity. ObjectID: f098701a-6681-4aca-97b0-380391a21c39
PrimaryKey field: DefectId. Type: System.Int32. Value: 448
Method Enter: CollectionCore.Remove
Entity to Remove Description:
Entity: CodeReviewer.EntityClasses.DefectEntity. ObjectID: f098701a-6681-4aca-97b0-380391a21c39
PrimaryKey field: DefectId. Type: System.Int32. Value: 448
Method Enter: EntityBase.CheckForRefetch
Method Exit: EntityBase.CheckForRefetch: already refetching or isdirty.
Method Enter: EntityBase.CheckForRefetch
Method Exit: EntityBase.CheckForRefetch: already refetching or isdirty.
Method Enter: EntityBase.CheckForRefetch
Method Exit: EntityBase.CheckForRefetch: already refetching or isdirty.
Method Enter: EntityBase.CheckForRefetch
Method Exit: EntityBase.CheckForRefetch: state is not OutOfSync
Method Enter: EntityBase.CheckForRefetch
Method Exit: EntityBase.CheckForRefetch: already refetching or isdirty.
Method Enter: EntityBase.CheckForRefetch
Method Exit: EntityBase.CheckForRefetch: state is not OutOfSync
Method Enter: EntityBase.CheckForRefetch
Method Exit: EntityBase.CheckForRefetch: state is not OutOfSync
Method Enter: EntityBase.CheckForRefetch
Method Exit: EntityBase.CheckForRefetch: state is not OutOfSync
Method Enter: EntityBase.CheckForRefetch
Method Exit: EntityBase.CheckForRefetch: already refetching or isdirty.
Method Enter: EntityBase.CheckForRefetch
Method Exit: EntityBase.CheckForRefetch: already refetching or isdirty.
Method Exit: CollectionCore.Remove
Method Enter: EntityBase.CheckForRefetch
Method Exit: EntityBase.CheckForRefetch: already refetching or isdirty.
Method Enter: EntityBase.CheckForRefetch
Method Exit: EntityBase.CheckForRefetch: already refetching or isdirty.
Method Enter: EntityBase.CheckForRefetch
Method Exit: EntityBase.CheckForRefetch: already refetching or isdirty.
Method Enter: EntityBase.CheckForRefetch
Method Exit: EntityBase.CheckForRefetch: state is not OutOfSync
Method Enter: EntityBase.CheckForRefetch
Method Exit: EntityBase.CheckForRefetch: already refetching or isdirty.
Method Enter: EntityBase.CheckForRefetch
Method Exit: EntityBase.CheckForRefetch: state is not OutOfSync
Method Enter: EntityBase.CheckForRefetch
Method Exit: EntityBase.CheckForRefetch: state is not OutOfSync
Method Enter: EntityBase.CheckForRefetch
Method Exit: EntityBase.CheckForRefetch: state is not OutOfSync
Method Enter: EntityBase.SyncFKFields
Active Entity Description:
Entity: CodeReviewer.EntityClasses.DefectEntity. ObjectID: f098701a-6681-4aca-97b0-380391a21c39
PrimaryKey field: DefectId. Type: System.Int32. Value: 448
Data Supplying Entity Description:
Entity: CodeReviewer.EntityClasses.DefectSeverityEntity. ObjectID: f098701a-6681-4aca-97b0-380391a21c39
PrimaryKey field: DefectSeverityId. Type: System.Int32. Value: 1031
Syncing FK field DefectSeverityId with PK field DefectSeverityId Method Enter: EntityBase.CheckForRefetch Method Exit: EntityBase.CheckForRefetch: already refetching or isdirty. Method Enter: EntityBase.CheckForRefetch Method Exit: EntityBase.CheckForRefetch: already refetching or isdirty. Method Enter: EntityBase.CheckForRefetch Method Exit: EntityBase.CheckForRefetch: already refetching or isdirty. Method Enter: EntityBase.CheckForRefetch Method Exit: EntityBase.CheckForRefetch: state is not OutOfSync Method Enter: EntityBase.CheckForRefetch Method Exit: EntityBase.CheckForRefetch: already refetching or isdirty. Method Enter: EntityBase.CheckForRefetch Method Exit: EntityBase.CheckForRefetch: state is not OutOfSync Method Enter: EntityBase.CheckForRefetch Method Exit: EntityBase.CheckForRefetch: state is not OutOfSync Method Enter: EntityBase.CheckForRefetch Method Exit: EntityBase.CheckForRefetch: state is not OutOfSync Method Exit: EntityBase.SyncFKFields Index of added entity: 1 Method Exit: CollectionCore.PerformAdd Method Enter: EntityBase.CheckForRefetch Method Exit: EntityBase.CheckForRefetch: state is not OutOfSync
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 12-May-2008 22:27:03   

Syncing FK field DefectSeverityId with PK field DefectSeverityId

so it was set. but, is that field marked as changed ? You state an entity gets marked as dirty without setting a value, so we've to track down why that entity is set to be dirty, this only happens if a field gets set with a different value. You still haven't answered my question: which field is marked as changed in the dirty marked entity?

I can't reproduce any of this behavior.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 254
Joined: 16-Nov-2006
# Posted on: 12-May-2008 22:32:25   

You state an entity gets marked as dirty without setting a value

I presume you meant "setting a different value"?

The DefectSeverityId field is marked as changed. I've actually attached a screen shot of the entityfield in the debugger after the value is set to hopefully help you further.

Posts: 254
Joined: 16-Nov-2006
# Posted on: 12-May-2008 22:33:53   

I can also put a break point in any of the llblgen runtime source if you want and tell you the values if that helps?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 13-May-2008 12:50:07   

I think this is indeed what we fixed in v2.6: if you do: myOrder.Customer = myCustomer; myOrder.Customer = myCustomer;

you'll see that myOrder.CustomerId is marked as changed. The reason is that when the second time the entity is assigned, the code first performs a DEREFERENCE of the current customer, however that's the SAME instance, but it doesn't check for this.

So the result of that is that the FK field is reset to null, because the related entity is dereferenced.

Then the assignment is performed and the FK field is synced with the PK field, getting the value it had before the dereference action, however because it goes from null to a real value, it is seen as a change.

In v2.6, we don't dereference the related entity anymore if it's the same entity nor do we do a re-assignment, so nothing is done really.

To work around this in v2.5, you've to check yourself if the value is the same instance before the assignment. You now always set the related entity, you should wrap that in an if, so the assignment only takes place if the entity is different.

Frans Bouma | Lead developer LLBLGen Pro