question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

EntityHistoryHelper shouldn't create a PropertyChange for unchanged property

See original GitHub issue

https://github.com/aspnetboilerplate/aspnetboilerplate/blob/7d7d34efd46c2fdf64ad6601bdece1453c08d8b6/src/Abp.ZeroCore.EntityFrameworkCore/EntityHistory/EntityHistoryHelper.cs#L299-L303

Let’s assume that we have not audited entity with a few properties, but only one of them is audited.

Current behavior: modifying other (non-audited properties) will cause EntityHistoryHelper to create a PropertyChange for audited property (even though it is unchanged).

Expected behavior:

propertyChange.NewValue = propertyEntry.GetNewValue()?.ToJsonString().TruncateWithPostfix(EntityPropertyChange.MaxValueLength);
if (!isAuditedProperty || propertyChange.OriginalValue == propertyChange.NewValue)
{
    // No change
    propertyChangesToRemove.Add(propertyChange);
}

Unchanged property shall should be removed from entity history if it’s (1) not audited OR (2) unmodified.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:7 (6 by maintainers)

github_iconTop GitHub Comments

2reactions
4nonym0uscommented, Feb 14, 2020

Has inaccurate comparison when dealing with large string/data. (string/data was being truncated before comparison)

In this case I’d suggest comparing hashes of both OriginalValue and NewValue as simply trimming both values is incorrect. Apparently, we need to store these hashes as a part of EntityPropertyChange.

1reaction
4nonym0uscommented, Oct 30, 2020

@demirmusa

First of all, there is no need not to trust the description and provided solution as it has already been discussed by 3 people, you could just apply the solution, cover that with unit-test and resolve the issue.

The first code snipped you’ve attached is not an “expected behavior” and If you were to check if issue is still present, you could just take a look at issue creation time (it has been made on 14th of Feb, 2020 while the latest change to EntityHistoryHelper.cs (on dev branch) is dated Feb 7, 2020).

The only difference is logical operator in IF-statement: Actual: if (!isAuditedProperty && propertyChange.OriginalValue == propertyChange.NewValue) Exepcted: if (!isAuditedProperty || propertyChange.OriginalValue == propertyChange.NewValue)

Related test-case should look like this:

        [Fact]
        public void Should_Not_Save_Empty_PropertyChanges()
        {
            // Arrange
            // Forward calls from substitute to implementation
            var entityHistoryStore = Resolve<EntityHistoryStore>();
            _entityHistoryStore.When(x => x.SaveAsync(Arg.Any<EntityChangeSet>()))
                .Do(callback => AsyncHelper.RunSync(() =>
                    entityHistoryStore.SaveAsync(callback.Arg<EntityChangeSet>()))
                );
            _entityHistoryStore.When(x => x.Save(Arg.Any<EntityChangeSet>()))
                .Do(callback => entityHistoryStore.Save(callback.Arg<EntityChangeSet>()));

            // Act
            Foo foo = null;
            WithUnitOfWork(() =>
            {
                foo = new Foo
                {
                    Audited = "s1"
                };
                _fooRepository.InsertAndGetId(foo);
                
            });

            UsingDbContext((context) =>
            {
                context.EntityChanges.Count(e => e.TenantId == 1).ShouldBe(1);
                context.EntityChangeSets.Count(e => e.TenantId == 1).ShouldBe(1);
                context.EntityPropertyChanges.Count(e => e.TenantId == 1).ShouldBe(1);
            });

            WithUnitOfWork(() =>
            {
                foo.NonAudited = "s2";
                _fooRepository.Update(foo);
            });

            // Assert
            UsingDbContext((context) =>
            {
                context.EntityChanges.Count(e => e.TenantId == 1).ShouldBe(1);
                context.EntityChangeSets.Count(e => e.TenantId == 1).ShouldBe(1);
                context.EntityPropertyChanges.Count(e => e.TenantId == 1).ShouldBe(1);
            });
        }
    public class Foo : Entity
    {
        [Audited]
        public string Audited { get; set; }

        public string NonAudited { get; set; }
    }
Read more comments on GitHub >

github_iconTop Results From Across the Web

EntityHistoryHelper shouldn't create a PropertyChange for ...
Appears to be working correctly except for datetime? properties are ... shouldn't create a PropertyChange for unchanged property #6294.
Read more >
After setting EntityState.Unchanged the entity properties ...
After saving my changes, I have the correct student record in the database and also the book record remains unchanged, but whenever I...
Read more >
Articles Tutorials | AspNet Boilerplate
Entity History tracks changes to complex type properties as property changes (unlike owned entities for EF Core). The original/new values of a complex...
Read more >
Result of Change in Control, and/or Change in Ownership
Legal Entity Ownership Program (LEOP) – Result of Change in Control and/or Change in Ownership. The property that will be subject to reassessment...
Read more >
Tax Reassessments of Transferred Property
Under Proposition 13,1 real property located in California is gen- erally reassessed when it is purchased, newly constructed, or a. “change in ownership”...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found