使用IDbContextFactory时出现ObjectDisposedException错误,如何解决?
错误原因及解决方案
错误原因
你遇到的System.ObjectDisposedException,本质是IQueryable的延迟执行特性导致的:
- 你在
using代码块内创建DbContext实例,并构建了查询返回IQueryable<AppUser>对象 using块结束时,DbContext会被自动调用Dispose()释放所有资源- 但
IQueryable并不会立即执行数据库查询,它只是保存查询逻辑;实际执行(比如绑定到UI、调用ToList()等)是在using块外部进行的,此时DbContext已经被销毁,自然无法访问上下文实例,抛出异常。
你的完整代码
@inject IDbContextFactory<IdentityContext> _contextFactory @code { IQueryable<AppUser> FilteredCountries { get { using (var context = _contextFactory.CreateDbContext()) { var itemsQueryable = context.Set<AppUser>().AsQueryable(); var result = itemsQueryable?.Where(c => c.AccessFailedCount <= maxMedals); if (!string.IsNullOrEmpty(nameFilter)) { result = result.Where(c => c.UserName.Contains(nameFilter)); } if (minMedals > 0) { result = result.Where(c => c.AccessFailedCount >= minMedals); } return result; } } } }
修复方案
方案1:立即执行查询,返回内存集合(推荐)
将IQueryable转换为内存集合(比如List<AppUser>),在using块内部完成数据库查询操作,这样后续操作的是内存中的数据,不再依赖已被释放的DbContext:
@inject IDbContextFactory<IdentityContext> _contextFactory @code { List<AppUser> FilteredCountries { get { using (var context = _contextFactory.CreateDbContext()) { var itemsQueryable = context.Set<AppUser>().AsQueryable(); var result = itemsQueryable?.Where(c => c.AccessFailedCount <= maxMedals); if (!string.IsNullOrEmpty(nameFilter)) { result = result.Where(c => c.UserName.Contains(nameFilter)); } if (minMedals > 0) { result = result.Where(c => c.AccessFailedCount >= minMedals); } // 立即执行查询,把结果加载到内存中 return result?.ToList() ?? new List<AppUser>(); } } } }
方案2:在数据使用时创建并销毁DbContext(适合异步场景)
如果需要异步查询,或者希望在组件的生命周期内按需获取数据,可以将查询逻辑封装为异步方法,在需要数据的地方调用,确保DbContext在查询完成后再释放:
@inject IDbContextFactory<IdentityContext> _contextFactory @code { List<AppUser> FilteredUsers { get; set; } = new List<AppUser>(); async Task LoadFilteredUsersAsync() { using (var context = _contextFactory.CreateDbContext()) { var itemsQueryable = context.Set<AppUser>().AsQueryable(); var result = itemsQueryable?.Where(c => c.AccessFailedCount <= maxMedals); if (!string.IsNullOrEmpty(nameFilter)) { result = result.Where(c => c.UserName.Contains(nameFilter)); } if (minMedals > 0) { result = result.Where(c => c.AccessFailedCount >= minMedals); } FilteredUsers = await result?.ToListAsync() ?? new List<AppUser>(); } } // 组件初始化时加载数据 protected override async Task OnInitializedAsync() { await LoadFilteredUsersAsync(); } // 过滤条件变化时重新加载数据 async Task OnFilterChanged() { await LoadFilteredUsersAsync(); } }
内容的提问来源于stack exchange,提问作者mz1378
相关产品推荐
相关产品推荐

