【发布时间】:2022-09-27 15:15:56
【问题描述】:
我在 ASP.NET 核心应用程序上收到以下异常:
\"在配置时尝试使用上下文。不能在 \'OnConfiguring\' 中使用 DbContext 实例,因为此时仍在配置它。如果在此上下文上启动第二个操作,则可能会发生这种情况在上一个操作完成之前。不保证任何实例成员都是线程安全的。\"
我知道它产生该错误的原因。我的应用程序中的多个线程同时尝试初始化 DBContext,即从前端接收多个请求都访问相同的方法
public async Task<IEnumerable<T>> QueryAsync<T>(string sqlStmt, Parameter[] inputParameters = null)
{
if (inputParameters is null)
return await Database.GetDbConnection().QueryAsync<T>(sqlStmt);
paramsList = new DynamicParameters();
paramsList.AddParamater(inputParameters);
return await Database.GetDbConnection().QueryAsync<T>(sqlStmt, paramsList); <--Here the exception is raised
}
如果想知道 \'Database\' 指的是什么,那么它是 EFCore 6.0.9 的 DbContext 类中的 DatabaseFacade 类型属性;这是代码:
namespace Microsoft.EntityFrameworkCore{
public class DbContext :
IInfrastructure<IServiceProvider>,
IDbContextDependencies,
IDbSetCache,
IDbContextPoolable
{
private readonly DbContextOptions _options;
private IDictionary<(Type Type, string? Name), object>? _sets;
private IDbContextServices? _contextServices;
private IDbContextDependencies? _dbContextDependencies;
private DatabaseFacade? _database;
/// <summary>
/// Provides access to database related information and operations for this context.
/// </summary>
public virtual DatabaseFacade Database
{
get
{
CheckDisposed();
return _database ??= new DatabaseFacade(this);
}
}
}}
我在 Startup.cs 的 ConfigureServices 方法中注入 DBContext,因此我无法为每个线程创建多个 DBContext。
此外,在配置上下文时,DBContext 的服务生命周期设置为瞬态:
services.AddDbContextFactory<MyQueryDbContext>(options => options.UseSqlServer(MyQuery, sqlServerOptions => sqlServerOptions.CommandTimeout(databaseTimeout)), ServiceLifetime.Transient);
MyQueryDbContext 看起来像这样:
public class MyQueryDbContext : MyDbCtx<MyQueryDbContext>, IMyQuery
{
public MyQueryDbContext(DbContextOptions<MyQueryDbContext> model) : base(model)
{
}
}
这是 MyDbCtx:
public class MyDbCtx<TContext> : DbContext
{
public MyDbCtx(DbContextOptions<TContext> model) : base(model)
{
}
}
因此,我没有显式覆盖 OnConfiguring 方法,因为我从外部提供了配置详细信息
我可以使该异步方法同步运行,但我还有哪些其他选择?
-
Database来自哪里以及如何使用?您发布的代码没有显示任何尝试从多个线程使用 DbContext。它显示了在 EF Core 之上使用 Dapper 的尝试,而不是仅仅打开一个连接。那不会产生你得到的错误。使此方法同步惯于修复使用 DbContext 作为 DbConnection 的错误 -
请发布您的
OnConfiguring代码以及您如何称呼QueryAsync。此代码是对 EF Core 的误用 - DbContext 不是数据库连接,它是一个短暂的工作单元,跟踪和持久化在单身的业务/应用程序“事务”。它并不意味着从多个线程中使用,因为它不需要。它也不是使用 SqlConnection 的替代方法 -
很多时候,这个错误是循环的结果,在第一个迭代完成之前执行下一次迭代。调试一下看看是不是这样。
标签: c# entity-framework asp.net-core dependency-injection