ASP.NET Core API - Second operation is started on Db context before a previous operation completed

Viewed 40

I'm receiving the following exception on ASP.NET core app:

"An attempt was made to use the context while it is being configured. A DbContext instance cannot be used inside 'OnConfiguring' since it is still being configured at this point. This can happen if a second operation is started on this context before a previous operation completed. Any instance members are not guaranteed to be thread safe."

I know the reason why it is generating that error. Multiple threads in my app are at the same time trying to initialize DBContext i.e. from the frontend, receiving multiple requests all accessing the same method

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
    }

If wondering what is that 'Database' referring to, then it is a DatabaseFacade type property inside DbContext class of EFCore 6.0.9; here's the code:

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);
        }
    }
 }}

I'm injecting DBContext in the ConfigureServices method of Startup.cs, hence I cannot create multiple DBContexts for each thread.

Also, service lifetime for DBContext is set to transient when configuring the context:

services.AddDbContextFactory<MyQueryDbContext>(options => options.UseSqlServer(MyQuery, sqlServerOptions => sqlServerOptions.CommandTimeout(databaseTimeout)), ServiceLifetime.Transient);

Where MyQueryDbContext looks like this:

public class MyQueryDbContext  : MyDbCtx<MyQueryDbContext>, IMyQuery
{
    public MyQueryDbContext(DbContextOptions<MyQueryDbContext> model) : base(model)
    {
    }
}

And here's the MyDbCtx:

public class MyDbCtx<TContext> : DbContext
{
    public MyDbCtx(DbContextOptions<TContext> model) : base(model)
    {
    }
}

So, I'm not explicitly overriding OnConfiguring method as I'm providing config details from outside

I can make that async method run synchronously but what other options do I have?

0 Answers
Related