I have a custom DbContext SnowflakeDbContext that I need to initialize with a SnowflakeDbConnection for it to work:
public class SnowflakeDbContext : DbContext
{
private readonly string connectionString = "";
public SnowflakeDbContext(DbContextOptions<SnowflakeDbContext> options) : base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
var dbConnection = new SnowflakeDbConnection()
{
ConnectionString = this.connectionString
};
optionsBuilder.UseSqlServer(dbConnection);
optionsBuilder.AddInterceptors(new SnowflakeCommandInterceptor());
}
public DbSet<Opportunity> Opportunities { get; set; } = default!;
public DbSet<Account> Accounts { get; set; } = default!;
}
This works well with EF Core 5, were in Startup.cs (I am using an ASP.NET Core 5 web application) I use
.AddDbContext<SnowflakeDbContext>(ServiceLifetime.Singleton)
I want to use the SnowflakeDbContext with HotChocolate where it is recommended that I use AddPooledDbContextFactory<> in order to support pooling of connections and allowing the system to make simultaneous calls (described here).
I have modified Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services
.AddPooledDbContextFactory<SnowflakeDbContext>(options =>
{
var dbConnection = new SnowflakeDbConnection()
{
ConnectionString = this.connectionString
};
options.UseSqlServer(dbConnection);
options.AddInterceptors(new SnowflakeCommandInterceptor());
})
.AddGraphQLServer()
.AddQueryType<Query>();
}
Using the following GraphQL query (which uses parallel queries):
query GetAccountsInParallel {
a: accounts {
id, name
}
b: accounts {
id, name
}
c: accounts {
id, name
}
}
I get the following error:
"No service for type 'SnowflakeGraphQL.Snowflake.SnowflakeDbContext' has been registered.",
I can add
.AddDbContext<SnowflakeDbContext>()
in Startup.cs after the call to .AddPooledDbContextFactory<>. Now I get a different error:
"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."
All of the examples I have seen on the web use .UseSqlServer(connectionString) where as I need to use the .UseSqlServer(dbConnection) version in order to be able to access our Snowflake database.
How do I configure my application in Startup.cs to use .AddPooledDbContextFactory()?
Update: Starting with the graphql-workshop code and replacing Sqlite with first SqlServer and then SqlServer using my SnowflakeDbContext I get it to work, so there must be a subtle difference somewhere in my code as described above that results in a failure in my case.
When retrieving the accounts records, we need to use the [ScopedService] rather than the [Service] like this:
[UseApplicationDbContext]
public async Task<List<Account>> GetAccounts([ScopedService] SnowflakeDbContext context) => await context.Accounts.ToListAsync();