abpframework / abp

Open-source web application framework for ASP.NET Core! Offers an opinionated architecture to build enterprise software solutions with best practices on top of the .NET. Provides the fundamental infrastructure, cross-cutting-concern implementations, startup templates, application modules, UI themes, tooling and documentation.
https://abp.io
GNU Lesser General Public License v3.0
12.47k stars 3.36k forks source link

Why ConcurrencyStamp not change when ValueObject updated #19962

Open 2501272126 opened 1 month ago

2501272126 commented 1 month ago

code example:

public class DateRange : ValueObject {
    public DateRange(DateOnly start, DateOnly end) {
        if (start > end) {
            throw new InvalidDataException("");
        }
        Start = start;
        End = end;
    }

    public DateOnly Start { get; private init; }

    public DateOnly End { get; private init; }

    protected override IEnumerable<object> GetAtomicValues() {
        yield return Start;
        yield return End;
    }
}

public class Program : AggregateRoot<Guid> {
    public string Name { get; private set; }
    public DateRange DateRange { get; private set; }
    public List<Item> Items { get; private init; } = new();

    public void Update(string name, DateRange dateRange, IEnumerable<Item> items) {
          Name = name;
          DateRange = dateRange;
          Items.Clear();
          Items.AddRange(items);
      }
}

var program = await _programRepository.GetAsync(id);
program.Update(name, dateRange, items);
await _programRepository.UpdateAsync(program, true);

when i update the Name field ConcurrencyStamp is worked, but when i update the DateRange or Items , database has changed and the ConcurrencyStamp not update.

maliming commented 3 weeks ago

hi

Can you try to override the HandlePropertiesBeforeSave method of AbpDbContext.

protected virtual void HandlePropertiesBeforeSave()
{
    var entries = ChangeTracker.Entries().ToList();
    foreach (var entry in entries)
    {
        HandleExtraPropertiesOnSave(entry);

        if (entry.State.IsIn(EntityState.Modified, EntityState.Deleted))
        {
            UpdateConcurrencyStamp(entry);
        }
    }

    if (EntityChangeOptions.Value.PublishEntityUpdatedEventWhenNavigationChanges)
    {
        foreach (var entry in AbpEfCoreNavigationHelper.GetChangedEntityEntries().Where(x => x.State == EntityState.Unchanged))
        {
            UpdateConcurrencyStamp(entry);
        }
    }
}