Не удается внедрить DbContext в репозиторий

#c# #asp.net-core #dependency-injection #dbcontext

#c# #asp.net-core #внедрение зависимости #dbcontext

Вопрос:

Я пытаюсь настроить DI для нового ASP.NET Основной сайт и у меня есть этот код:

 public void ConfigureServices(IServiceCollection services)
{
    services
        .AddMvc()
        .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

    // Get the configuration from the app settings.
    var config = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("appsettings.json")
        .Build();

    // Get app settings to configure things accordingly.
    var appSettings = Configuration.GetSection("AppSettings");
    var settings = new AppSettings();
    appSettings.Bind(settings);

    services
        .AddOptions()
        .Configure<AppSettings>(appSettings)
        .AddSingleton<IConfigurationRoot>(config)
        .AddDbContext<MyDbContext>(builder =>
        {
            builder.UseSqlServer(config.GetConnectionString("myConn"));
        }, ServiceLifetime.Transient, ServiceLifetime.Transient);

    services.AddSingleton<ILoadTestCleanUpServiceRepository, LoadTestCleanUpServiceRepository>();
        ...
  

Теперь LoadTestCleanUpServiceRepository зависит от MyDbContext :

 public class LoadTestCleanUpServiceRepository : ILoadTestCleanUpServiceRepository
{
    private readonly MyDbContext _dbContext;

    public LoadTestCleanUpServiceRepository(MyDbContext dbContext)
    {
        _dbContext = dbContext;
    }
    ...
  

..и контекст БД такой:

 public class MyDbContext : DbContext
{
    public MyDbContext(DbContextOptions<MyDbContext> ctxOptions) : base(ctxOptions)
    {
    }
}
  

Когда я запускаю приложение, я получаю эту ошибку:

Исключение InvalidOperationException: не удается разрешить службу для типа ‘MyCode.Инфраструктура.Обычный.MyDbContext’ при попытке активировать ‘MyCode.Инфраструктура.LoadTestCleanUpService.LoadTestCleanUpServiceRepository’.

Я попытался изменить ServiceLifetime параметры и добавить этот дополнительный код:

 services.AddTransient<MyDbContext>(sp => new MyDbContext(config));
  

… но, похоже, ничего не помогает, и я не могу понять, почему это не работает. Он пытается создать репозиторий, но почему он не может также создать контекст DB? Это даже не доходит до того момента, когда я вызываю UseSqlServer() !
Есть идеи?

ОБНОВЛЕНИЕ 1:

Хм… Теперь я вижу это. Скорее всего, это связано:

введите описание изображения здесь

ОБНОВЛЕНИЕ 2:

Теперь у меня есть :

  • Заменил EF 6 на Microsoft.EntityFrameworkCore.SQLServer
  • Обновлен до целевой платформы netcoreapp2.2 для решения некоторых конфликтующих версий сборки.
  • Сделал репозиторий ограниченным.

Но я все еще получаю ту же ошибку.

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

1. Почему класс MyDbContext имеет AcDbContext для конструктора? Этот код компилируется?

2. @Dimitar Извините. Теперь я это исправил. Я «меняю» некоторые части кодовых имен, чтобы избежать утечки информации о моем проекте. Это не какой-то сверхсекретный материал, но я стараюсь сделать код как можно более «общим».

3. У меня была похожая проблема, и да, несоответствие версии EF является единственным объяснением этого

4. Вы не можете использовать контекст базы данных с ограниченной областью действия в одноэлементной службе. Попытка сделать контекст базы данных временным также не исправит это. Подумайте о том, чтобы вместо этого ограничить область действия вашего репозитория.

5. Имейте в виду, что ваш MyDbContext находится в плену как зависимая внутри LoadTestCleanUpServiceRepository .

Ответ №1:

Я вижу, что вы зарегистрировались LoadTestCleanUpServiceRepository как Singleton , в то время как MyDbContext как Transient , а затем пытаетесь разрешить MyDbContext из LoadTestCleanUpServiceRepository . В этом проблема. Согласно ASP.NET Сроки службы ядра документация:

Опасно разрешать службу с ограниченной областью действия / временную службу из синглтона. Это может привести к некорректному состоянию службы при обработке последующих запросов.

Решение таково: зарегистрируйтесь LoadTestCleanUpServiceRepository и MyDbContext следующим образом:

 services.AddDbContext<MyDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("YourConnectionStringName")));

services.AddScoped<ILoadTestCleanUpServiceRepository, LoadTestCleanUpServiceRepository>();
  

Теперь проблема должна исчезнуть.

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

1. Спасибо. После многих изменений это сработало. Одна вещь, которая была действительно неправильной, заключалась в том, что я определил два разных контекста БД (случайно после попытки переместить один контекст БД), и это все испортило.