【问题标题】:System.InvalidOperationException: There is already an open DataReader associated with this Connection which must be closed firstSystem.InvalidOperationException:已经有一个打开的 DataReader 与此 Connection 关联,必须先关闭
【发布时间】:2022-03-24 16:39:53
【问题描述】:

我在调用下面的以下代码块时收到此错误。我在 SO 上看到的与此错误相关的所有内容都是由于人们调用了 using 块,我不是,但在幕后可能有一些我不知道被重复的代码?我也不确定如何找到这里复制的连接。有一些专业知识的人可以在这个问题上提供帮助吗?我的堆栈跟踪也在下面。

if (await _userManager.IsInRoleAsync(user, role.Name))

public class UserRolesModel : PageModel
    {
        private readonly UserManager<IdentityUser> _userManager;
        private readonly SignInManager<IdentityUser> _signInManager;
        private readonly RoleManager<IdentityRole> _roleManager;
        private readonly IAdminView _adminView;

        public UserRolesModel(UserManager<IdentityUser> userManager,
            SignInManager<IdentityUser> signInManager,
            RoleManager<IdentityRole> roleManager,
            IAdminView adminView)
        {
            _userManager = userManager;
            _signInManager = signInManager;
            _roleManager = roleManager;
            _adminView = adminView;
        }

        public EmployeeDto Employee { get; set; }

        public ManageUserRolesDto UserRoles { get; set; }
        public async Task OnGetAsync(string userId)
        {
            var userRoleList = new List<UserRolesDto>();
            var user = await _userManager.FindByIdAsync(userId);
            foreach (var role in _roleManager.Roles)
            {
                var userRolesDto = new UserRolesDto()
                {
                    RoleName = role.Name
                };
                
                if (await _userManager.IsInRoleAsync(user, role.Name))
                {
                    userRolesDto.Selected = true;
                }
                else
                {
                    userRolesDto.Selected = false;
                }
                userRoleList.Add(userRolesDto);
            }

            UserRoles = new ManageUserRolesDto()
            {
                UserId = userId,
                UserRoles = userRoleList
            };

            var employeeData = await _adminView.GetEmployeeDataByAspId(userId);

            var viewModel = new EmployeeViewDto
            {
                Employee = employeeData
            };
            
            Employee = new EmployeeDto
            {
                EmployeeAspId = employeeData.AspUserId,
                EmployeeViewDto = viewModel
            };


        }

        public async Task<IActionResult> OnPostAsync(string id, ManageUserRolesDto userRoles)
        {
            var user = await _userManager.FindByIdAsync(id);
            var roles = await _userManager.GetRolesAsync(user);
            var result = await _userManager.RemoveFromRolesAsync(user, roles);
            result = await _userManager.AddToRolesAsync(user, userRoles.UserRoles.Where(x => x.Selected).Select(y => y.RoleName));
            var currentUser = await _userManager.GetUserAsync(User);
            await _signInManager.RefreshSignInAsync(currentUser);
            await Data.Seeds.DefaultUsers.SeedSuperAdminAsync(_userManager, _roleManager);
            return RedirectToPage("/Admin/Index"); 
        }
    }

堆栈跟踪

System.InvalidOperationException: There is already an open DataReader associated with this Connection which must be closed first.
   at Microsoft.Data.SqlClient.SqlCommand.<>c.<ExecuteDbDataReaderAsync>b__169_0(Task`1 result)
   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.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(DbContext _, Boolean result, 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.Query.ShapedQueryCompilingExpressionVisitor.SingleOrDefaultAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Query.ShapedQueryCompilingExpressionVisitor.SingleOrDefaultAsync[TSource](IAsyncEnumerable`1 asyncEnumerable, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore`9.IsInRoleAsync(TUser user, String normalizedRoleName, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Identity.UserManager`1.IsInRoleAsync(TUser user, String role)
   at Navrae.WebApp.Pages.RoleManager.UserRolesModel.OnGetAsync(String userId) in C:\Users\Work Laptop\source\repos\Navrae\Navrae.WebApp\Pages\RoleManager\UserRoles.cshtml.cs:line 45
   at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.ExecutorFactory.NonGenericTaskHandlerMethod.Execute(Object receiver, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeHandlerMethodAsync()
   at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeNextPageFilterAsync()
   at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.Rethrow(PageHandlerExecutedContext context)
   at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker.InvokeInnerFilterAsync()
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

【问题讨论】:

  • 尝试将foreach (var role in _roleManager.Roles)更改为foreach (var role in _roleManager.Roles.ToList())
  • 我切换回本地数据库,它工作正常。不确定它是否是我在 SQL 服务器上的设置导致问题。
  • 对于 SQL Server,你必须启用 MARS -“多个活动结果集”,谷歌它,你应该找到如何配置你的连接字符串来启用它。
  • 我根据您的建议对其进行了测试,并且成功了。我不知道为什么。也许 MARS 的研究会给出答案。谢谢@LasseV.Karlsen!
  • 不同之处在于,使用.ToList(),您在进入循环体之前消耗了Roles 集合,这意味着就数据库连接而言,您已经完成了角色的迭代。没有它,当您还尝试执行 IsInRoleAsync 时,您将针对 Roles 集合的数据库打开结果集,然后还尝试获取结果集。

标签: sql asp.net-core entity-framework-core sqldatareader


【解决方案1】:

按照 Lasse V. Karlsen 的建议,使用 .ToList() 关闭数据读取器。下面提到了我必须为此修复引入的一些更改。

包含 ToList()

var dbData = dbContext.Table.Where(x=>x.ID=x).ToList();  //Include .ToList()

包括 dbContext.Update(model)

foreach(var data in dbData)
{
    //do work
    dbContext.Update(data); //Update model
    dbContext.SaveChanges(); //Save it now or later
}
dbContext?.Dispose(); //depends on your code structure.

希望这会有所帮助。 MARS 也可以是一个选项,但我没有尝试过,因为 ToList() 解决方案解决了我的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-17
    • 2020-09-25
    • 2011-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-23
    • 2013-07-18
    相关资源
    最近更新 更多