Base solution for your next web application

Activities of "tom.ohle"

Hi maliming,

We tried the approach below but we are still seeing the same performance issue on a brand new ASP.NET Zero 8.7.0 project (ASP.NET Core & Angular).

foreach (var user in users)
{
    await _userRoleRepository.DeleteAsync(r => r.RoleId == role.Id && r.UserId == user.Id);
}

We are currently looking for the root cause of this issue, but in the meantime we would appreciate your thoughts on how we might resolve this issue.

Thanks!

Hi maliming,

I am assuming what you meant is to replace this....

foreach (var user in users)
{
    CheckErrors(await UserManager.RemoveFromRoleAsync(user, role.Name));
}

...with this...

foreach (var user in users)
{
    await _userRoleRepository.DeleteAsync(r => r.RoleId == role.Id && r.UserId == user.Id);
}

If so, does that mean calls to CheckErrors and UserManager.RemoveFromRoleAsync are not important? Do we run the risk of introducing a regression by using the lower level approach?

Hey aaron,

To mitigate this issue, do you see any red flags with setting the expiration to 7 days instead of 1 year?

public class MyProjectWebCoreModule : AbpModule
{
    public override void PreInitialize()
    {
        Configuration.BackgroundJobs.UserTokenExpirationPeriod = TimeSpan.FromDays(7);
    }
}
Answer

ok thanks that does look like what we've been looking for

The RoleAppService.DeleteRole method takes a very long time when the role to be deleted is currently assigned to a large number of users. In my case it is assigned to 20,000 users, and the call that takes the longest is UserManager.RemoveFromRoleAsync as you can see in the screenshot below.

It seems like the call to UserManager.RemoveFromRoleAsync decreases in performance when there are more than a small number of users assigned to the role (ie. the performance is drastically better when less than a hundred users are assigned).

Is this a known issue? Is there a recommended approach for working around this issue, or should I start thinking about how to come up with my own solution?

This behavior can be reproduced by dropping the following method into an application service in a brand new ASP.NET Zero 8.7.0 project (ASP.NET Core & Angular).

public void CreateTestUsers()
{
    // create 20000 test users
    
    var context = CurrentUnitOfWork.GetDbContext<MyDbContext>();
    
    for (var i = 0; i < 20000; ++i)
    {
        var first = $@"first{i}";
        var last = $@"last{i}";
        var userName = $@"{first}.{last}";
        var emailAddress = $@"{userName}@dummy.com";
        
        var user = new User
        {
            EmailAddress = emailAddress,
            IsEmailConfirmed = true,
            Name = first,
            Surname = last,
            UserName = userName,
            Password = "AM4OLBpptxBYmM79lGOX9egzZk3vIQU3d/gFCJzaBjAPXzYIK3tQ2N7X4fcrHtElTw==", //123qwe
            TenantId = 1,
        };

        user.SetNormalizedNames();
        context.Users.Add(user);
    }
    
    context.SaveChanges();
    
    // assign users to test role
    
    var userIds = context.Users.Select(user => user.Id).ToList();
    
    foreach (var userId in userIds)
    {
        context.UserRoles.Add(new UserRole
        {
            RoleId = 6,
            UserId = userId,
            TenantId = 1,
            CreationTime = DateTime.Now,
            CreatorUserId = 1,
        });
    }
    
    context.SaveChanges();
}

Thanks for reading!

Question

We are looking into using a shared redis cache server between several aspnetzero applications. We would be using a microservice to update some of the cache values so the information would remain the same for all of these applications.

The issue we're seeing with this approach is that each aspnetzero application uses a standard cache names for certain things ie (AbpZeroUserPermission, AbpZeroRolePermissions, AbpZeroLanguages, etc..)

Is there a way to alter these cache names or override them in some manner to give them a prefix of some sort so they would be unique accross all applications that would share the cache?

Hi maliming,

Thanks for the quick response! I have couple of questions though.

  • Why is a new 1 year token created every time the admin user logs in? Why are the old 1 year tokens not deleted automatically when the admin user logs in?

  • Is this the definition of the UserTokenExpirationWorker? It appears to only delete tokens that have expired. Am I missing something that explains how the 1 year tokens are supposed to be cleaned up?

This behavior is exhibited by a brand new instance of a 8.7.0 ASP.NET Core & Angular project.

Is this expected behavior?

The login performance for the admin user gets worse and worse as the number of records grows in this table.

Also, we noticed the performance degredation after upgrading from 7.3.1 to 8.7.0 in our development environment, which had over 10,000 records for the admin user in AbpUserTokens table.

The project has been built upon the "<PROJECTNAME>-aspnetzero-7.3.1" ZIP archive and is still using EF Core 2.2.6.

Showing 11 to 20 of 50 entries