From d041aeb1fa2fc1b5dd231d32ab7d5ecd0c0e77d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?SAL=C4=B0H=20=C3=96ZKARA?= Date: Tue, 30 Dec 2025 15:58:32 +0300 Subject: [PATCH] Improve JSON navigation property change tracking Refactored EntityHistoryHelper to better handle property changes for navigation properties mapped to JSON. Now, nested property changes are prefixed with the navigation property name, and duplicate property names are handled to avoid conflicts. --- .../EntityHistory/EntityHistoryHelper.cs | 60 +++++++++++-------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/EntityHistory/EntityHistoryHelper.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/EntityHistory/EntityHistoryHelper.cs index 7554c1d281..66e632dc8c 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/EntityHistory/EntityHistoryHelper.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/EntityHistory/EntityHistoryHelper.cs @@ -202,37 +202,47 @@ public class EntityHistoryHelper : IEntityHistoryHelper, ITransientDependency } } - if (AbpEfCoreNavigationHelper != null) + if (AbpEfCoreNavigationHelper == null) { - foreach (var (navigationEntry, index) in entityEntry.Navigations.Select((value, i) => ( value, i ))) - { - var propertyInfo = navigationEntry.Metadata.PropertyInfo; - if (propertyInfo != null && - propertyInfo.IsDefined(typeof(DisableAuditingAttribute), true)) - { - continue; - } + return propertyChanges; + } - if (AbpEfCoreNavigationHelper.IsNavigationEntryModified(entityEntry, index)) + foreach (var (navigationEntry, index) in entityEntry.Navigations.Select((value, i) => ( value, i ))) + { + var propertyInfo = navigationEntry.Metadata.PropertyInfo; + if (propertyInfo != null && + propertyInfo.IsDefined(typeof(DisableAuditingAttribute), true)) + { + continue; + } + + if (navigationEntry.Metadata.TargetEntityType.IsMappedToJson() && navigationEntry is ReferenceEntry referenceEntry && referenceEntry.TargetEntry != null) + { + foreach (var propertyChange in GetPropertyChanges(referenceEntry.TargetEntry)) { - var abpNavigationEntry = AbpEfCoreNavigationHelper.GetNavigationEntry(entityEntry, index); - if (navigationEntry.Metadata.TargetEntityType.IsMappedToJson() && navigationEntry is ReferenceEntry referenceEntry && referenceEntry.TargetEntry != null) - { - var jsonPropertyChanges = GetPropertyChanges(referenceEntry.TargetEntry); - propertyChanges.AddRange(jsonPropertyChanges); - } - else + if (propertyChanges.Any(pc => pc.PropertyName == propertyChange.PropertyName)) { - var isCollection = navigationEntry.Metadata.IsCollection; - propertyChanges.Add(new EntityPropertyChangeInfo - { - PropertyName = navigationEntry.Metadata.Name, - PropertyTypeFullName = navigationEntry.Metadata.ClrType.GetFirstGenericArgumentIfNullable().FullName!, - OriginalValue = GetNavigationPropertyValue(abpNavigationEntry?.OriginalValue, isCollection), - NewValue = GetNavigationPropertyValue(abpNavigationEntry?.CurrentValue, isCollection) - }); + propertyChange.PropertyName = $"{referenceEntry.Metadata.Name}.{propertyChange.PropertyName}"; } + + propertyChanges.Add(propertyChange); } + + continue; + } + + if (AbpEfCoreNavigationHelper.IsNavigationEntryModified(entityEntry, index)) + { + var abpNavigationEntry = AbpEfCoreNavigationHelper.GetNavigationEntry(entityEntry, index); + + var isCollection = navigationEntry.Metadata.IsCollection; + propertyChanges.Add(new EntityPropertyChangeInfo + { + PropertyName = navigationEntry.Metadata.Name, + PropertyTypeFullName = navigationEntry.Metadata.ClrType.GetFirstGenericArgumentIfNullable().FullName!, + OriginalValue = GetNavigationPropertyValue(abpNavigationEntry?.OriginalValue, isCollection), + NewValue = GetNavigationPropertyValue(abpNavigationEntry?.CurrentValue, isCollection) + }); } }