ASP.NET Core Identity多表查询时遇MySqlConnection已释放错误
解决ASP.NET Core Identity关联查询时的System.ObjectDisposedException错误
问题描述
System.ObjectDisposedException: '无法访问已释放的对象。对象名称: 'MySqlConnection'。'
在使用ASP.NET Core Identity的Users、UserRoles、Roles表进行关联查询时,执行以下代码始终抛出上述错误:
var customers = await context.Users .Join(context.UserRoles, user => user.Id, urole => urole.UserId, (user, urole) => new { user, urole }) .Join(context.Roles, a => a.urole.RoleId, role => role.Id, (a, role) => new { a, role }) .Where(s => s.role.Name == role.SystemRole) .ToListAsync();
常见原因及解决方案
1. 检查DbContext生命周期
这个错误核心原因是查询执行前DbContext已被释放:
- 若使用依赖注入,确保DbContext采用
Scoped生命周期(ASP.NET Core默认配置),保证在当前请求周期内实例不会被提前释放。 - 若手动创建DbContext,需确保在
await查询完成前,不要调用Dispose()方法,可使用using语句包裹且异步操作在块内完成:using var context = new YourDbContext(); var customers = await context.Users...ToListAsync();
2. 排查外部变量引用问题
代码中role.SystemRole的role变量若来自外部已释放的上下文实例,会导致关联查询时访问已释放的资源。建议将目标角色名称提前赋值到本地变量,再用于查询:
var targetRoleName = systemRoleValue; // 提前获取角色名称到本地变量 var customers = await context.Users .Join(context.UserRoles, user => user.Id, urole => urole.UserId, (user, urole) => new { user, urole }) .Join(context.Roles, a => a.urole.RoleId, role => role.Id, (a, role) => new { a, role }) .Where(s => s.role.Name == targetRoleName) .ToListAsync();
3. 使用Identity导航属性简化查询
ASP.NET Core Identity已内置实体间的导航属性,无需手动写Join,既简洁又能避免生命周期问题:
var targetRoleName = systemRoleValue; var customers = await context.Users .Include(u => u.UserRoles) .ThenInclude(ur => ur.Role) .Where(u => u.UserRoles.Any(ur => ur.Role.Name == targetRoleName)) .ToListAsync();
4. 确保异步操作正确等待
调用查询的代码必须正确使用await,若未等待异步操作完成就释放DbContext,也会触发该错误。比如控制器Action需定义为async Task<IActionResult>,并等待查询完成:
public async Task<IActionResult> GetCustomers() { var customers = await _context.Users...ToListAsync(); return Ok(customers); }
内容的提问来源于stack exchange,提问作者TheColonel
相关产品推荐
相关产品推荐

