EF. The connection was not closed. The connection's current state is connecting

asp.net asp.net-core c# entity-framework entity-framework-core

Question

I have jwt auth:

var messageHandlers = new JwtMessageHandler(_serviceProvider);

app.UseJwtBearerAuthentication(new JwtBearerOptions
{
    AutomaticAuthenticate = true,
    AutomaticChallenge = true,
    Events = new JwtBearerEvents
    {
        OnMessageReceived = messageHandlers.OnMessageReceived,
    },
    TokenValidationParameters = tokenValidationParameters
});

The JwtMessageHandler is my custom handler. In the handler I have to make some queries to database, so I pass ServiceProvider and resolve my user service:

public class JwtMessageHandler
{

        private IUserService _userService;  

        public async Task OnMessageReceived(MessageReceivedContext arg)
        {
             //parsing header, get claims from token
             ...
              _userService = (IUserService)arg.HttpContext.RequestServices.GetService(typeof(IUserService));
             var isRoleChanged = await _userService.IsRoleChanged(tokenObject.Subject, rolesFromToken);

            if (isRoleChanged)
            {
                GenerateBadResponse(arg);
                return;
            }

            var canLogin = await _userService.CanLogin(tokenObject.Subject);

            if (!canLogin)
            {
                GenerateBadResponse(arg);
                return;
            }
        }    
}

In the service I make queries:

...
 var user = await _userManager.FindByEmailAsync(email);
 var currentRoles = await _userManager.GetRolesAsync(user);
..

The OnMessageReceived is called for every request. When I have one request on page to the server or I wait one-two seconds before doing something all works fine. But, I have several pages where I make 2-3 simultaneous requests to the server. And, in this case I get error about:

The connection was not closed. The connection's current state is connecting

I understand that problem with multithreading. The JwtMessageHandler is created once when application is started. So, I put the line:

_userService = (IUserService)_serviceProvider.GetService(typeof(IUserService)); 

inside method, before it was located in the constructor. But, It didn't help. Also, I tried to set null to _userService in the end of my method.

How to correctly use in this case?

1
6
11/24/2017 3:02:47 PM

Accepted Answer

Trying to use a connection that is already "connecting" - clear sign of some race condition.

  1. Re-check that IUserService is registered with "scope" lifetime, and all it dependencies (userManager, dbContext) too
  2. Do not use IServiceProvider you obtained during app startup for scope-bases services resolution - it is NOT related to current request scope and return instances from "some other universe". Use HttpContext.RequestServices for service resolution.
  3. Check that your are "awaiting" all async methods. If you start second request while still executing first one - you may possibly "catch" dbContext during "connecting" stage.
  4. Your JwtMessageHandler instance is one/single per app. So don't use it's property for storing _userService (remove private IUserService _userService). Instead, use local variable inside OnMessageReceived (var _userService = ...).

You already checked (1), (2) and (3). I think (4) is the last one you need to fix your bug.

13
12/19/2016 12:23:12 PM

Popular Answer

I have faced this situation a lot. I have always gotten by by using lock keyword.

lock (_context)
{
      var user = _context.users.first(x => x.Id == userId);
}

This locks the use of the object (i.e. _context) for the current thread and no other thread simultaneously can access this same instance hence no problems whatsoever.



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