AddPooledDbContextFactory с DbContext, использующим пользовательское подключение к базе данных: служба не зарегистрирована

#asp.net-core #.net-core #entity-framework-core #snowflake-cloud-data-platform #hotchocolate

Вопрос:

У меня есть пользовательский DbContext SnowflakeDbContext, который мне нужно инициализировать с помощью SnowflakeDbConnection, чтобы он работал:

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

Это хорошо работает с EF Core 5, были в Startup.cs (я использую ASP.NET Веб-приложение Core 5) Я использую

       .AddDbContext<SnowflakeDbContext>(ServiceLifetime.Singleton)
 

Я хочу использовать SnowflakeDbContext с HotChocolate, где рекомендуется использовать AddPooledDbContextFactory<><> для поддержки объединения соединений и предоставления системе возможности совершать одновременные вызовы (описано здесь).

Я изменил файл 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>();
        }
 

Используя следующий запрос GraphQL (который использует параллельные запросы):

 query GetAccountsInParallel {
  a: accounts {
    id, name
  }
  b: accounts {
    id, name
  }
  c: accounts {
    id, name
  }
}
 

Я получаю следующую ошибку:

 "No service for type 'SnowflakeGraphQL.Snowflake.SnowflakeDbContext' has been registered.",
 

Я могу добавить

       .AddDbContext<SnowflakeDbContext>()
 

в Startup.cs после вызова .AddPooledDbContextFactory<>. Теперь я получаю другую ошибку:

 "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."
 

Все примеры, которые я видел в Интернете, используют .UseSqlServer(строка подключения), где мне нужно использовать версию .UseSqlServer(DbConnection), чтобы иметь доступ к нашей базе данных Snowflake.

Как настроить мое приложение в Startup.cs для использования .AddPooledDbContextFactory()?

Обновление: Начиная с кода graphql-workshop и заменяя Sqlite сначала на SQLServer, а затем на SQLServer, используя мой SnowflakeDbContext, я заставляю его работать, поэтому где-то в моем коде должна быть небольшая разница, как описано выше, которая приводит к сбою в моем случае.

Комментарии:

1. Используете ли вы более одного DbContext?

2. @u1986237 нет, я использую только SnowflakeDbContext, но мой запрос GraphQL GetAccountsInParallel вызывает 3 запроса параллельно (один и тот же код запроса для всех 3).

Ответ №1:

При извлечении записей учетных записей нам нужно использовать [ScopedService], а не [Службу], как это:

    [UseApplicationDbContext]
   public async Task<List<Account>> GetAccounts([ScopedService] SnowflakeDbContext context) => await context.Accounts.ToListAsync();