EF。接続は閉じられませんでした。接続の現在の状態は接続しています

asp.net asp.net-core c# entity-framework 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はすべての要求に対して呼び出されます。サーバーに1つのリクエストがあったり、何かをする前に1〜2秒待っても問題ありません。しかし、私は2-3の同時リクエストをサーバーに作成するいくつかのページを持っています。そして、この場合、私は次のことについてエラーになります:

接続は閉じられませんでした。接続の現在の状態は接続しています

私はマルチスレッドの問題を理解しています。 JwtMessageHandlerは、アプリケーションの起動時に一度作成されます。だから、私は次のように書いています。

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

コンストラクタ内に配置される前に、内部メソッドを呼び出します。しかし、それは助けにはなりませんでした。また、メソッドの最後にnullを_userServiceに設定しようとしました。

この場合正しく使用するには?

受け入れられた回答

既に「接続中」の接続を使用しようとしています - 競合状態のサインをクリアしてください。

  1. IUserServiceが "スコープ"存続期間とすべての依存関係(userManager、dbContext)にも登録されていることを再確認してください
  2. スコープベースのサービス解決のためにアプリケーションの起動時に取得したIServiceProviderを使用しないでください。現在の要求スコープに関連せず、 "他のユニバース"からインスタンスを返します。サービスの解決にはHttpContext.RequestServicesを使用します。
  3. あなたがすべての非同期メソッドを「待っている」ことを確認してください。最初のリクエストをまだ実行している間に2番目のリクエストを開始すると、 "接続中"のステージでdbContextを "キャッチ"する可能性があります。
  4. JwtMessageHandlerインスタンスは、アプリケーションごとに1つずつです。したがって、それを使用しないでください_userServiceprivate IUserService _userService削除する)を格納するためのプロパティです。代わりに、 OnMessageReceivedvar _userService = ... )の内部でローカル変数を使用します。

あなたはすでに(1)、(2)、(3)をチェックしています。私は(4)あなたのバグを修正するために必要な最後のものだと思う。


人気のある回答

@ドミトリーの答えは正しい方向に私を指摘した。私にとっては、.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);
}


Related

ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ