Activities of "maliming"

hi

Can you share a template project to reproduce the problem?

You can also disable Dynamic Claims in all projects and try again.

https://abp.io/docs/latest/framework/fundamentals/dynamic-claims#enabling-disabling-the-dynamic-claims

Thanks.

hi

Can you add some code to the Program to read and log the AbpLicenseCode from appsettings.json

Thanks.

hi

AI is right.

You can override the DefaultHttpExceptionStatusCodeFinder.

https://github.com/abpframework/abp/blob/dev/framework/src/Volo.Abp.AspNetCore/Volo/Abp/AspNetCore/ExceptionHandling/DefaultHttpExceptionStatusCodeFinder.cs#L70-L73

Thanks.

hi

Please use IRemoteStreamContent to replace IFormFile in your DTO and regenerate the Angular proxy.

https://abp.io/docs/latest/framework/architecture/domain-driven-design/application-services#working-with-streams

Thanks.

hi

The new version

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Metadata;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities;

namespace Volo.Abp.EntityFrameworkCore.ChangeTrackers;

public class MyAbpEntityEntry
{
    public string Id { get; set; }

    public EntityEntry EntityEntry { get; set; }

    public List<MyAbpNavigationEntry> NavigationEntries { get; set; }

    private bool _isModified;
    public bool IsModified
    {
        get
        {
            return _isModified || EntityEntry.State == EntityState.Modified || NavigationEntries.Any(n => n.IsModified);
        }
        set => _isModified = value;
    }

    public MyAbpEntityEntry(string id, EntityEntry entityEntry)
    {
        Id = id;
        EntityEntry = entityEntry;
        NavigationEntries = EntityEntry.Navigations.Select(x => new MyAbpNavigationEntry(x, x.Metadata.Name)).ToList();
    }

    public void UpdateNavigation(EntityEntry entityEntry, MyAbpNavigationEntry navigationEntry)
    {
        if (IsModified ||
            EntityEntry.State == EntityState.Modified ||
            navigationEntry.IsModified)
        {
            return;
        }

        var currentValue = navigationEntry.NavigationEntry.CurrentValue;
        if (currentValue == null)
        {
            return;
        }

        if (navigationEntry.NavigationEntry is CollectionEntry)
        {
            navigationEntry.OriginalValue!.As<List<object>>().Add(entityEntry.Entity);
        }
        else
        {
            navigationEntry.OriginalValue = currentValue;
        }
    }
}

public class MyAbpNavigationEntry
{
    public NavigationEntry NavigationEntry { get; set; }

    public string Name { get; set; }

    public bool IsModified { get; set; }

    public object? OriginalValue { get; set; }

    public object? CurrentValue => NavigationEntry.CurrentValue;

    public MyAbpNavigationEntry(NavigationEntry navigationEntry, string name)
    {
        NavigationEntry = navigationEntry;
        Name = name;
        if (navigationEntry.CurrentValue != null )
        {
            OriginalValue = navigationEntry is CollectionEntry ? new List<object>() : navigationEntry.CurrentValue;
        }
    }
}


[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(AbpEfCoreNavigationHelper))]
public class MyAbpEfCoreNavigationHelper : AbpEfCoreNavigationHelper
{
    protected Dictionary<string, MyAbpEntityEntry> MyEntityEntries { get; } = new();

    public override void ChangeTracker_Tracked(object? sender, EntityTrackedEventArgs e)
    {
        EntityEntryTrackedOrStateChanged(e.Entry);
        DetectChanges(e.Entry);
    }

    public override void ChangeTracker_StateChanged(object? sender, EntityStateChangedEventArgs e)
    {
        EntityEntryTrackedOrStateChanged(e.Entry);
        DetectChanges(e.Entry);
    }

    protected override void EntityEntryTrackedOrStateChanged(EntityEntry entityEntry)
    {
        if (entityEntry.State != EntityState.Unchanged)
        {
            return;
        }

        var entryId = GetEntityEntryIdentity(entityEntry);
        if (entryId == null)
        {
            return;
        }

        if (MyEntityEntries.ContainsKey(entryId))
        {
            return;
        }

        MyEntityEntries.Add(entryId, new MyAbpEntityEntry(entryId, entityEntry));
    }

    protected override void DetectChanges(EntityEntry entityEntry, bool checkEntityEntryState = true)
    {
        #pragma warning disable EF1001
        var stateManager = entityEntry.Context.GetDependencies().StateManager;
        var internalEntityEntityEntry = stateManager.TryGetEntry(entityEntry.Entity, throwOnNonUniqueness: false);
        if (internalEntityEntityEntry == null)
        {
            return;
        }

        var foreignKeys = entityEntry.Metadata.GetForeignKeys().ToList();
        foreach (var foreignKey in foreignKeys)
        {
            var principal = stateManager.FindPrincipal(internalEntityEntityEntry, foreignKey);
            if (principal == null)
            {
                continue;
            }

            var entryId = GetEntityEntryIdentity(principal.ToEntityEntry());
            if (entryId == null || !MyEntityEntries.TryGetValue(entryId, out var myAbpEntityEntry))
            {
                continue;
            }

            var navigationEntry = myAbpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is INavigation navigationMetadata && navigationMetadata.ForeignKey == foreignKey) ??
                                  myAbpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is ISkipNavigation skipNavigationMetadata && skipNavigationMetadata.ForeignKey == foreignKey);

            if (navigationEntry != null && checkEntityEntryState && entityEntry.State == EntityState.Unchanged)
            {
                myAbpEntityEntry.UpdateNavigation(entityEntry, navigationEntry);
            }

            if (!myAbpEntityEntry.IsModified && (!checkEntityEntryState || IsEntityEntryChanged(entityEntry)))
            {
                myAbpEntityEntry.IsModified = true;
                DetectChanges(myAbpEntityEntry.EntityEntry, false);
            }

            if (navigationEntry != null && IsEntityEntryChanged(entityEntry))
            {
                navigationEntry.IsModified = true;
            }
        }

        var skipNavigations = entityEntry.Metadata.GetSkipNavigations().ToList();
        foreach (var skipNavigation in skipNavigations)
        {
            var joinEntityType = skipNavigation.JoinEntityType;
            var foreignKey = skipNavigation.ForeignKey;
            var inverseForeignKey = skipNavigation.Inverse.ForeignKey;
            foreach (var joinEntry in stateManager.Entries)
            {
                if (joinEntry.EntityType != joinEntityType || stateManager.FindPrincipal(joinEntry, foreignKey) != internalEntityEntityEntry)
                {
                    continue;
                }

                var principal = stateManager.FindPrincipal(joinEntry, inverseForeignKey);
                if (principal == null)
                {
                    continue;
                }

                var entryId = GetEntityEntryIdentity(principal.ToEntityEntry());
                if (entryId == null || !MyEntityEntries.TryGetValue(entryId, out var myAbpEntityEntry))
                {
                    continue;
                }

                var navigationEntry = myAbpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is INavigation navigationMetadata && navigationMetadata.ForeignKey == inverseForeignKey) ??
                                      myAbpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is ISkipNavigation skipNavigationMetadata && skipNavigationMetadata.ForeignKey == inverseForeignKey);

                if (navigationEntry != null && checkEntityEntryState && entityEntry.State == EntityState.Unchanged)
                {
                    myAbpEntityEntry.UpdateNavigation(entityEntry, navigationEntry);
                }

                if (!myAbpEntityEntry.IsModified  && (!checkEntityEntryState || IsEntityEntryChanged(entityEntry)))
                {
                    myAbpEntityEntry.IsModified = true;
                    DetectChanges(myAbpEntityEntry.EntityEntry, false);
                }

                if (navigationEntry != null && (!checkEntityEntryState || IsEntityEntryChanged(entityEntry)))
                {
                    navigationEntry.IsModified = true;
                }
            }
        }
#pragma warning restore EF1001
    }

    protected override bool IsEntityEntryChanged(EntityEntry entityEntry)
    {
        return entityEntry.State == EntityState.Added ||
               entityEntry.State == EntityState.Deleted ||
               entityEntry.State == EntityState.Modified;
    }

    public override List<EntityEntry> GetChangedEntityEntries()
    {
        return MyEntityEntries
            .Where(x => x.Value.IsModified)
            .Select(x => x.Value.EntityEntry)
            .ToList();
    }

    public override bool IsEntityEntryModified(EntityEntry entityEntry)
    {
        if (entityEntry.State == EntityState.Modified)
        {
            return true;
        }

        var entryId = GetEntityEntryIdentity(entityEntry);
        if (entryId == null)
        {
            return false;
        }

        return MyEntityEntries.TryGetValue(entryId, out var myAbpEntityEntry) && myAbpEntityEntry.IsModified;
    }

    public override bool IsNavigationEntryModified(EntityEntry entityEntry, int? navigationEntryIndex = null)
    {
        var entryId = GetEntityEntryIdentity(entityEntry);
        if (entryId == null)
        {
            return false;
        }

        if (!MyEntityEntries.TryGetValue(entryId, out var myAbpEntityEntry))
        {
            return false;
        }

        if (navigationEntryIndex == null)
        {
            return myAbpEntityEntry.NavigationEntries.Any(x => x.IsModified);
        }

        var navigationEntryProperty = myAbpEntityEntry.NavigationEntries.ElementAtOrDefault(navigationEntryIndex.Value);
        return navigationEntryProperty != null && navigationEntryProperty.IsModified;
    }

    public override AbpNavigationEntry? GetNavigationEntry(EntityEntry entityEntry, int navigationEntryIndex)
    {
        var entryId = GetEntityEntryIdentity(entityEntry);
        if (entryId == null)
        {
            return null;
        }

        if (!MyEntityEntries.TryGetValue(entryId, out var myAbpEntityEntry))
        {
            return null;
        }

        var element = myAbpEntityEntry.NavigationEntries.ElementAtOrDefault(navigationEntryIndex);
        if (element == null)
        {
            return null;
        }

        return new AbpNavigationEntry(element.NavigationEntry, element.Name)
        {
            IsModified = element.IsModified,
            OriginalValue = element.OriginalValue
        };
    }

    protected override string? GetEntityEntryIdentity(EntityEntry entityEntry)
    {
        if (entityEntry.Entity is IEntity entryEntity && entryEntity.GetKeys().Length == 1)
        {
            return $"{entityEntry.Metadata.ClrType.FullName}:{entryEntity.GetKeys().FirstOrDefault()}";
        }

        return null;
    }

    public override void RemoveChangedEntityEntries()
    {
        MyEntityEntries.RemoveAll(x => x.Value.IsModified);
    }

    public override void Clear()
    {
        MyEntityEntries.Clear();
    }
}

Hi

I will create a test project and check the results if you don’t have time to prepare the demo.

Thanks

Hi

I will check if we can refactor this function.

Thanks

Hi

I will check this case with your project.

Thanks

Hi

If you can share a minimal project I can check it, maybe we can improve more performance.

Thanks

hi

Can you try to override the AbpEfCoreNavigationHelper in your project?

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Metadata;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities;

namespace Volo.Abp.EntityFrameworkCore.ChangeTrackers;

public class MyAbpEntityEntry
{
    public string Id { get; set; }

    public EntityEntry EntityEntry { get; set; }

    public List<AbpNavigationEntry> NavigationEntries { get; set; }

    private bool _isModified;
    public bool IsModified
    {
        get
        {
            return _isModified || EntityEntry.State == EntityState.Modified || NavigationEntries.Any(n => n.IsModified);
        }
        set => _isModified = value;
    }

    public MyAbpEntityEntry(string id, EntityEntry entityEntry)
    {
        Id = id;
        EntityEntry = entityEntry;
        NavigationEntries = EntityEntry.Navigations.Select(x => new AbpNavigationEntry(x, x.Metadata.Name)).ToList();
    }

    public void UpdateNavigationEntries()
    {
        foreach (var navigationEntry in NavigationEntries)
        {
            if (IsModified ||
                EntityEntry.State == EntityState.Modified ||
                navigationEntry.IsModified ||
                navigationEntry.NavigationEntry.IsModified)
            {
                continue;
            }

            var currentValue = AbpNavigationEntry.GetOriginalValue(navigationEntry.NavigationEntry.CurrentValue);
            if (currentValue == null)
            {
                continue;
            }
            switch (navigationEntry.OriginalValue)
            {
                case null:
                    navigationEntry.OriginalValue = currentValue;
                    break;
                case IEnumerable originalValueCollection when currentValue is IEnumerable currentValueCollection:
                {
                    var existingList = originalValueCollection.Cast<object?>().ToList();
                    var newList = currentValueCollection.Cast<object?>().ToList();
                    if (newList.Count > existingList.Count)
                    {
                        navigationEntry.OriginalValue = currentValue;
                    }

                    break;
                }
                default:
                    navigationEntry.OriginalValue = currentValue;
                    break;
            }
        }
    }
}

[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(AbpEfCoreNavigationHelper))]
public class MyAbpEfCoreNavigationHelper : AbpEfCoreNavigationHelper
{
    protected Dictionary<string, MyAbpEntityEntry> MyEntityEntries { get; } = new();

    public override void ChangeTracker_Tracked(object? sender, EntityTrackedEventArgs e)
    {
        EntityEntryTrackedOrStateChanged(e.Entry);
        DetectChanges(e.Entry);
    }

    public override void ChangeTracker_StateChanged(object? sender, EntityStateChangedEventArgs e)
    {
        EntityEntryTrackedOrStateChanged(e.Entry);
        DetectChanges(e.Entry);
    }

    protected override void EntityEntryTrackedOrStateChanged(EntityEntry entityEntry)
    {
        if (entityEntry.State != EntityState.Unchanged)
        {
            return;
        }

        var entryId = GetEntityEntryIdentity(entityEntry);
        if (entryId == null)
        {
            return;
        }

        if (MyEntityEntries.ContainsKey(entryId))
        {
            return;
        }

        MyEntityEntries.Add(entryId, new MyAbpEntityEntry(entryId, entityEntry));
    }

    protected override void DetectChanges(EntityEntry entityEntry, bool checkEntityEntryState = true)
    {
        #pragma warning disable EF1001
        var stateManager = entityEntry.Context.GetDependencies().StateManager;
        var internalEntityEntityEntry = stateManager.TryGetEntry(entityEntry.Entity, throwOnNonUniqueness: false);
        if (internalEntityEntityEntry == null)
        {
            return;
        }

        var foreignKeys = entityEntry.Metadata.GetForeignKeys().ToList();
        foreach (var foreignKey in foreignKeys)
        {
            var principal = stateManager.FindPrincipal(internalEntityEntityEntry, foreignKey);
            if (principal == null)
            {
                continue;
            }

            var entryId = GetEntityEntryIdentity(principal.ToEntityEntry());
            if (entryId == null || !MyEntityEntries.TryGetValue(entryId, out var myAbpEntityEntry))
            {
                continue;
            }

            myAbpEntityEntry.UpdateNavigationEntries();
            if (!myAbpEntityEntry.IsModified && (!checkEntityEntryState || IsEntityEntryChanged(entityEntry)))
            {
                myAbpEntityEntry.IsModified = true;
                DetectChanges(myAbpEntityEntry.EntityEntry, false);
            }

            var navigationEntry = myAbpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is INavigation navigationMetadata && navigationMetadata.ForeignKey == foreignKey) ??
                                  myAbpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is ISkipNavigation skipNavigationMetadata && skipNavigationMetadata.ForeignKey == foreignKey);
            if (navigationEntry != null && IsEntityEntryChanged(entityEntry))
            {
                navigationEntry.IsModified = true;
            }
        }

        var skipNavigations = entityEntry.Metadata.GetSkipNavigations().ToList();
        foreach (var skipNavigation in skipNavigations)
        {
            var joinEntityType = skipNavigation.JoinEntityType;
            var foreignKey = skipNavigation.ForeignKey;
            var inverseForeignKey = skipNavigation.Inverse.ForeignKey;
            foreach (var joinEntry in stateManager.Entries)
            {
                if (joinEntry.EntityType != joinEntityType || stateManager.FindPrincipal(joinEntry, foreignKey) != internalEntityEntityEntry)
                {
                    continue;
                }

                var principal = stateManager.FindPrincipal(joinEntry, inverseForeignKey);
                if (principal == null)
                {
                    continue;
                }

                var entryId = GetEntityEntryIdentity(principal.ToEntityEntry());
                if (entryId == null || !MyEntityEntries.TryGetValue(entryId, out var myAbpEntityEntry))
                {
                    continue;
                }

                myAbpEntityEntry.UpdateNavigationEntries();
                if (!myAbpEntityEntry.IsModified  && (!checkEntityEntryState || IsEntityEntryChanged(entityEntry)))
                {
                    myAbpEntityEntry.IsModified = true;
                    DetectChanges(myAbpEntityEntry.EntityEntry, false);
                }

                var navigationEntry = myAbpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is INavigation navigationMetadata && navigationMetadata.ForeignKey == inverseForeignKey) ??
                                      myAbpEntityEntry.NavigationEntries.FirstOrDefault(x => x.NavigationEntry.Metadata is ISkipNavigation skipNavigationMetadata && skipNavigationMetadata.ForeignKey == inverseForeignKey);
                if (navigationEntry != null && (!checkEntityEntryState || IsEntityEntryChanged(entityEntry)))
                {
                    navigationEntry.IsModified = true;
                }
            }
        }
#pragma warning restore EF1001
    }

    protected override bool IsEntityEntryChanged(EntityEntry entityEntry)
    {
        return entityEntry.State == EntityState.Added ||
               entityEntry.State == EntityState.Deleted ||
               entityEntry.State == EntityState.Modified;
    }

    public override List<EntityEntry> GetChangedEntityEntries()
    {
        return MyEntityEntries
            .Where(x => x.Value.IsModified)
            .Select(x => x.Value.EntityEntry)
            .ToList();
    }

    public override bool IsEntityEntryModified(EntityEntry entityEntry)
    {
        if (entityEntry.State == EntityState.Modified)
        {
            return true;
        }

        var entryId = GetEntityEntryIdentity(entityEntry);
        if (entryId == null)
        {
            return false;
        }

        return MyEntityEntries.TryGetValue(entryId, out var myAbpEntityEntry) && myAbpEntityEntry.IsModified;
    }

    public override bool IsNavigationEntryModified(EntityEntry entityEntry, int? navigationEntryIndex = null)
    {
        var entryId = GetEntityEntryIdentity(entityEntry);
        if (entryId == null)
        {
            return false;
        }

        if (!MyEntityEntries.TryGetValue(entryId, out var myAbpEntityEntry))
        {
            return false;
        }

        if (navigationEntryIndex == null)
        {
            return myAbpEntityEntry.NavigationEntries.Any(x => x.IsModified);
        }

        var navigationEntryProperty = myAbpEntityEntry.NavigationEntries.ElementAtOrDefault(navigationEntryIndex.Value);
        return navigationEntryProperty != null && navigationEntryProperty.IsModified;
    }

    public override AbpNavigationEntry? GetNavigationEntry(EntityEntry entityEntry, int navigationEntryIndex)
    {
        var entryId = GetEntityEntryIdentity(entityEntry);
        if (entryId == null)
        {
            return null;
        }

        if (!MyEntityEntries.TryGetValue(entryId, out var myAbpEntityEntry))
        {
            return null;
        }

        return myAbpEntityEntry.NavigationEntries.ElementAtOrDefault(navigationEntryIndex);
    }

    protected override string? GetEntityEntryIdentity(EntityEntry entityEntry)
    {
        if (entityEntry.Entity is IEntity entryEntity && entryEntity.GetKeys().Length == 1)
        {
            return $"{entityEntry.Metadata.ClrType.FullName}:{entryEntity.GetKeys().FirstOrDefault()}";
        }

        return null;
    }

    public override void RemoveChangedEntityEntries()
    {
        MyEntityEntries.RemoveAll(x => x.Value.IsModified);
    }

    public override void Clear()
    {
        MyEntityEntries.Clear();
    }
}

Showing 1621 to 1630 of 11554 entries
Learn More, Pay Less
33% OFF
All Trainings!
Get Your Deal
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.1.0-preview. Updated on December 17, 2025, 07:08
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.