EF。连接没有关闭。连接的当前状态正在连接

时间:2016-12-19 07:42:33

标签: c# asp.net entity-framework asp.net-core entity-framework-core

我有jwt auth:

var messageHandlers = new JwtMessageHandler(_serviceProvider);

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

JwtMessageHandler是我的自定义处理程序。在处理程序中,我必须对数据库进行一些查询,因此我通过ServiceProvider并解析我的用户服务:

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;
            }
        }    
}

在服务中我提出疑问:

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

为每个请求调用OnMessageReceived。 当我在服务器页面上有一个请求或者我在做某事之前等待一到两秒钟一切正常。但是,我有几个页面,我同时向服务器发出2-3个请求。并且,在这种情况下,我得到关于的错误:

  

连接未关闭。连接的当前状态是连接

我理解多线程的问题。应用程序启动时会创建一次JwtMessageHandler。所以,我把这行:

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

inside方法,在它位于构造函数中之前。但是,它没有任何帮助。另外,我尝试在方法结束时将null设置为_userService

在这种情况下如何正确使用?

3 个答案:

答案 0 :(得分:9)

尝试使用已经“连接”的连接 - 明确某些竞争条件的迹象。

  1. 重新检查IUserService是否已注册“scope”生命周期,以及所有依赖项(userManager,dbContext)
  2. 不要使用在应用启动期间获得的IServiceProvider作为基于范围的服务解析 - 它与当前请求范围无关,并从“其他某个Universe”返回实例。使用HttpContext.RequestServices进行服务解析。
  3. 检查您是否“等待”所有异步方法。如果在仍然执行第一个请求时启动第二个请求 - 您可能会在“连接”阶段“捕获”dbContext。
  4. 您的JwtMessageHandler个实例是每个应用一个/单个。所以不要使用它的属性来存储_userService(删除private IUserService _userService)。相反,请在OnMessageReceivedvar _userService = ...)。
  5. 中使用局部变量

    您已经检查过(1),(2)和(3)。我认为(4)是你需要修复bug的最后一个。

答案 1 :(得分:0)

@Dmitry的回答指出了我正确的方向。对我来说,我在.NETCORE的MiddleWare中遇到了这个问题。为我解决这个问题的是在我的中间件的 Invoke 方法中解析IUnitOfWork接口。

我做了类似

的事情
public Task Invoke(HttpContext context)
{
    _unitOfWork = (IUnitOfWork)context.RequestServices.GetService(typeof(IUnitOfWork));

       //Some checks            

        var apiKey = context.Request.Headers["X-ApiKey"][0];

        var clientApp = _unitOfWork.ClientApplicationsRepository.Items.FirstOrDefault(s => s.ApiKey == apiKey);

     //Some other code...

    return _next(context);
}

答案 2 :(得分:0)

我经常面对这种情况。 我一直都是通过使用lock关键字来获得的。

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

这将锁定当前线程的对象(即_context)的使用,并且其他线程无法同时访问同一实例,因此没有任何问题。