Question

I have an application that uses Microsoft.AspNetCore.Identity.UserManager to manage users. I use core 2.2. UserManager is injected by built-in dependency injection in my services (not by me). like this:

public MyService(UserManager<IdentityUser> userManager)
{
   _userManager = userManager;
}

When I try to get a user by Id (FindByIdAsync) for the first time I see a request to db in a console. Next requests with the same Id I do not see any request to db, but the application works and got user.

In Startup.cs I do not have a configuration for userManager. I just use the extension method:

public void ConfigureServices(IServiceCollection services)
        {
            services
                .AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(
                Configuration.GetConnectionString("MyConnectionString"));
            services
                .AddIdentity<IdentityUser, IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
            services.AddMvc();
            var configService = new ConfigurationService(Configuration);
            services
                .AddIdentityServer()
                .AddDeveloperSigningCredential()
                .AddInMemoryApiResources(configService.GetApiResources())
                .AddInMemoryClients(configService.GetClients())
                .AddTestUsers(configService.GetUsers());
        }

Question: Maybe there is a way how to configure this caching feature in UserManager? Point me out where to get information about how long this cache leaves.

1
1
3/26/2019 3:33:32 PM

Popular Answer

I digged through the Identity source code on Github and ended in UserStore:

public override Task<TUser> FindByIdAsync(string userId, CancellationToken cancellationToken = default(CancellationToken))
{
    cancellationToken.ThrowIfCancellationRequested();
    ThrowIfDisposed();
    var id = ConvertIdFromString(userId);
    return UsersSet.FindAsync(new object[] { id }, cancellationToken);
}

UsersSet beeing of type DbSet<TUser>, Identity has no way to manage caching directly but relies on EF internals.

Digging into EF source code, I ended in DbContext:

object IDbSetCache.GetOrAddSet(IDbSetSource source, Type type)
{
    CheckDisposed();

    if (_sets == null)
    {
        _sets = new Dictionary<Type, object>();
    }

    if (!_sets.TryGetValue(type, out var set))
    {
        set = source.Create(this, type);
        _sets[type] = set;
    }

    return set;
}

and it looks like that there is a caching mechanism backed by a plain and simple Dictionary.

However, as Matt G. pointed in his comment, the solution to manage caching lies a level above your service: it is related to how you manage your dependency scope when injecting the UserManager.

2
3/26/2019 2:56:30 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow