2016-11-14 2 views
3

У меня возникли проблемы с введением пользовательского IAsyncQueryProvider при использовании EntityFrameworkCore. Точнее. У меня возникают проблемы с инъекцией поставщика при использовании предоставленных функций базы данных памяти. Используя поставщика по умолчанию (SqlServer), все работает нормально.UseInMemoryDatabase с UseInternalServiceProvider. Нет настроенного поставщика базы данных

Вот мой глобальный Startup.cs

private void ConfigureEntityFrameworkWithSecurity(IServiceCollection services) 
{ 
    services 
     .AddEntityFramework() 
     .AddEntityFrameworkSqlServer() 
     .AddScoped<IAsyncQueryProvider, CustomEntityProvider>() 
     .AddDbContext<APIContext>((sp, options) => 
     { 
      options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")) 
       .UseInternalServiceProvider(sp); 
     }); 
} 

Это работает безупречно, и я могу поставить точку останова в CustomEntityProvider, чтобы убедиться, что он действительно впрыскивается. На данный момент CustomEntityProvider просто реализует IAsyncQueryProvider и просто передает запрос. В ней нет логики.

Когда я бегу тест, я настроить вебхостинг использовать другой Startup файл:

public class TestStartup : Startup 
{ 
    public TestStartup(IHostingEnvironment env) : base(env) 
    { 
    } 

    public override void ConfigureServices(IServiceCollection services) 
    { 
     services 
      .AddDbContext<APIContext>((sp, options) => 
      { 
       options.UseInMemoryDatabase() 
        .UseInternalServiceProvider(sp); 
      }); 
     base.ConfigureServices(services); 
    } 
} 

Запуск теста с TestStartup дает ошибку:

System.InvalidOperationException : No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions object in its constructor and passes it to the base constructor for DbContext.

APIContext И это правильно не определено:

public class APIContext : DbContext 
{ 
    public APIContext(DbContextOptions<APIContext> options) 
     : base(options) 
    { 
    } 
    ... 
} 

Удаление UseInternalServiceProvider от TestStartup работает правильно - однако я не хочу, чтобы мои тесты попадали в фактическую базу данных. Кроме того, я ожидал бы, что UseInMemoryDatabase будет автоматически вводить зависимости поставщику услуг, поскольку он отлично работает сам по себе.

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

ответ

5

К сожалению, решение просты. Однако, похоже, очень мало документации об использовании инъекции зависимостей с функциональностью базы данных в памяти. Кажется, это тот или другой. Надеюсь, этот вопрос предоставит помощь будущим людям, достаточно неудачным, чтобы справиться с этим.

Я скачал источник EntityFramework расследовать, и обнаружил, что вызов UseInMemoryDatabase создает расширение InMemoryOptionsExtension который сам добавит к поставщику услуг, а именно:

public virtual void ApplyServices(IServiceCollection services) 
{ 
    Check.NotNull(services, nameof(services)); 

    services.AddEntityFrameworkInMemoryDatabase(); 
} 

И решение так просто, как это выглядит:

public class TestStartup : Startup 
{ 
    public TestStartup(IHostingEnvironment env) : base(env) 
    { 
    } 

    public override void ConfigureServices(IServiceCollection services) 
    { 
     services 
      .AddEntityFrameworkInMemoryDatabase() 
      .AddDbContext<APIContext>((sp, options) => 
      { 
       options.UseInMemoryDatabase().UseInternalServiceProvider(sp); 
      }); 
     base.ConfigureServices(services); 
    } 
} 
+0

Это точная ошибка, с которой я сталкиваюсь. Однако я использую EntityFramework.InMemory v2.0.0 и 'UseInMemoryDatabase()' устарел. Вы правы, документация ограничена, и я предполагаю 'services.AddEntityFrameworkInMemoryDatabase(). AddDbContext <' - это новый способ сделать это. Хотя каждый из них у меня есть, я все равно получаю ошибку. Есть ли вероятность, что вы обновили пакет Nuget за последний год? Благодарю. –

+0

@JeremyThompson В конце концов, я не очень сильно продвинул свой проект; это был скорее эксперимент с .netcore, чем что-либо еще. Я не уверен, что '.AddEntityFrameworkInMemoryDatabase' является * новым * способом сделать это. Насколько я помню, 'options.UseInMemoryDatabase()' настраивает контекст для использования провайдера в памяти, в то время как '.AddEntityFrameworkInMemoryDatabase()' настраивает инъекцию зависимостей - поэтому оба они должны быть указаны. Я посмотрю, когда буду дома, после обновления до последней. – Rob

+0

[Этот вопрос] (https://stackoverflow.com/questions/43098065) ​​или [этот] (https: // stackoverflow.com/questions/43991088) может быть связано с проблемой, с которой вы столкнулись – Rob

Смежные вопросы