使用两个DbContext实例并行查询时触发ObjectDisposedException问题
问题原因与解决方案
核心问题
你遇到的ObjectDisposedException根本原因不是DbContext的线程安全问题,而是EF Core的延迟执行特性导致的:
ctx1.MyClass.Where(x => x.ID == id)返回的是IQueryable<MyClass>,这只是一个待执行的查询表达式,并没有真正发起数据库请求,也不是异步任务。- 当
using块结束时,ctx1和ctx2会被立即释放,但此时你赋值给someData、someOtherData的只是未执行的查询。 - 等到调用
await Task.WhenAll(...)时,才会触发查询执行,但此时对应的DbContext已经被销毁,自然抛出上下文已释放的异常。
修复方案
要解决这个问题,必须在DbContext的using块内部,调用异步执行方法(比如ToListAsync())来启动查询任务,确保任务执行时上下文处于存活状态。修改后的代码如下:
Task<List<MyClass>> someDataTask; Task<List<MyOtherClass>> someOtherDataTask; using (MyContext ctx1 = new()) { // 在using块内调用ToListAsync,真正启动异步查询 someDataTask = ctx1.MyClass.Where(x => x.ID == id).ToListAsync(); } using (MyContext ctx2 = new()) { someOtherDataTask = ctx2.MyOtherClass.Where(x => x.ID == id).ToListAsync(); } await Task.WhenAll(someDataTask, someOtherDataTask); // 处理查询结果 var someData = someDataTask.Result; var someOtherData = someOtherDataTask.Result;
额外说明
- 你创建两个独立DbContext的思路是正确的,DbContext虽非线程安全,但这里每个任务对应各自的上下文实例,并行执行完全合法(只要每个上下文仅被一个线程操作)。
- 记住EF Core中所有返回
IQueryable的LINQ方法都是延迟执行的,只有调用ToListAsync()、FirstAsync()这类方法时,才会真正向数据库发送SQL请求。
内容的提问来源于stack exchange,提问作者WSC
相关产品推荐
相关产品推荐

