在 Blazor InteractiveServer 应用程序中,使用 ASP.NET 身份库,我调用: Microsoft.AspNetCore.Identity.UserManager`1.GetClaimsAsync(TUser 用户)
我通过在 Program.cs 中添加它来将其设置为使用我的扩展类
builder.Services.AddScoped<AuthenticationStateProvider, ExAuthenticationStateProvider>();
除了添加该行之外,对此的所有使用都是 Blazor 堆栈在选择时调用它。我唯一一次在这个类中直接调用任何东西是当我调用
ResetNextCheck()
时。
它抛出(下面是完整的堆栈跟踪)。
Microsoft.EntityFrameworkCore.Query - An exception occurred while iterating over the results of a query for context type 'LouisHowe.web.Areas.Identity.Data.UserDbContext'.
System.InvalidOperationException: Invalid operation. The connection is closed.
索赔表有 34 个条目,因此如果有要求(没有要求),读取整个表会很快。
我的应用程序中所有这些的一个非标准部分是我有
class ExIdentityUser : IdentityUser
,我在其中添加了 public bool Enabled { get; set; }
。所以我的 DbContext 是 UserDbContext : IdentityDbContext<ExIdentityUser>
。
这发生在我的
ExAuthenticationStateProvider : ServerAuthenticationStateProvider
GetAuthenticationStateAsync()
方法中。
为什么会在这次通话中关闭连接?
完整日志:
Error 08:52:21 [] Microsoft.EntityFrameworkCore.Database.Command - Failed executing DbCommand (19ms) [Parameters=[@__user_Id_0='?' (Size = 450)], CommandType='Text', CommandTimeout='30']
SELECT [a].[Id], [a].[ClaimType], [a].[ClaimValue], [a].[UserId]
FROM [AspNetUserClaims] AS [a]
WHERE [a].[UserId] = @__user_Id_0
// 20 irrelevant log messages
Error 08:52:22 [] Microsoft.EntityFrameworkCore.Query - An exception occurred while iterating over the results of a query for context type 'LouisHowe.web.Areas.Identity.Data.UserDbContext'.
System.InvalidOperationException: Invalid operation. The connection is closed.
at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.InitializeReaderAsync(AsyncEnumerator enumerator, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync() InvalidOperationException: Invalid operation. The connection is closed.
at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.InitializeReaderAsync(AsyncEnumerator enumerator, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
Error 08:52:22 [] LouisHowe.web.Services.ExAuthenticationStateProvider - GetAuthenticationStateAsync() exception: Invalid operation. The connection is closed. InvalidOperationException: Invalid operation. The connection is closed.
at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.InitializeReaderAsync(AsyncEnumerator enumerator, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserOnlyStore`6.GetClaimsAsync(TUser user, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Identity.UserManager`1.GetClaimsAsync(TUser user)
at LouisHowe.web.Services.ExAuthenticationStateProvider.GetAuthenticationStateAsync() in D:\a\LouisHowe\LouisHowe\LouisHowe.web\Services\ExAuthenticationStateProvider.cs:line 94
我修复了它(解释如下)。话虽如此,我不知道为什么会解决这个问题。
我用
UserManager<ExIdentityUser>
打电话:
userManager.FindByIdAsync(id);
userManager.GetClaimsAsync(user);
这些调用有时会失败,因为底层 DbConnection 已关闭。我不知道为什么,特别是有时对
FindByIdAsync()
的调用会成功,然后紧接着对 GetClaimsAsync()
的调用将具有关闭的连接。
为了解决这个问题,我将其更改为使用:
IDbContextFactory UserDbFactory; var dbContext = 等待 UserDbFactory.CreateDbContextAsync(); var user = wait dbContext.Users.Where(u => u.Id == id).FirstOrDefaultAsync(); var list = wait dbContext.UserClaims.Where(uc => uc.UserId == id).ToListAsync();
这不仅解决了我的 DbConnection 有时被关闭的问题,还解决了这个问题。正如我上面所说,不知道为什么。但是调用
UserManager
方法会导致 NotifyAuthenticationStateChanged()
失败。切换到 UserDbFactory
解决了这个问题以及其他问题。