dotnet runtime_error ai_generated true

System.InvalidOperationException: 在此上下文实例上完成上一个操作之前,又启动了第二个操作。这通常是由不同线程同时使用同一 DbContext 实例引起的。

System.InvalidOperationException: A second operation was started on this context instance before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext.

ID: dotnet/ef-core-sync-query-on-async-context

其他格式: JSON · Markdown 中文 · English
85%修复率
88%置信度
1证据数
2023-03-15首次发现

版本兼容性

版本状态引入弃用备注
Entity Framework Core 3.1 active
Entity Framework Core 5.0 active
Entity Framework Core 6.0 active
Entity Framework Core 7.0 active
Entity Framework Core 8.0 active

根因分析

DbContext 实例不是线程安全的,多个线程同时使用它,通常是由于同步调用阻塞异步操作或 DI 注册不当(例如,使用 Singleton 代替 Scoped)导致的。

English

A DbContext instance is not thread-safe and is being used concurrently from multiple threads, typically due to synchronous calls blocking async operations or improper DI registration (e.g., Singleton instead of Scoped).

generic

官方文档

https://learn.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency

解决方案

  1. Ensure DbContext is registered as Scoped in DI (default). For ASP.NET Core: services.AddDbContext<MyDbContext>(options => options.UseSqlServer(connectionString));
  2. Avoid mixing sync and async calls on the same DbContext. Use async methods (e.g., ToListAsync() instead of ToList()) consistently. If you must use sync, create a separate DbContext instance.
  3. Use DbContext pooling for high-throughput scenarios: services.AddDbContextPool<MyDbContext>(options => options.UseSqlServer(connectionString), poolSize: 128);

无效尝试

常见但无效的做法:

  1. Changing DbContext registration to Singleton to reuse the same instance globally. 95% 失败

    Singleton DbContext is not thread-safe and will cause the same error under concurrent requests; it also leads to stale data and memory leaks.

  2. Adding locks around all DbContext usage to serialize access. 85% 失败

    Locks defeat the purpose of async I/O and can cause deadlocks or severe performance degradation under load.

  3. Setting DbContext.PoolSize to a large number without configuring AddDbContextPool. 90% 失败

    PoolSize only applies when using DbContext pooling; without AddDbContextPool, it has no effect.