UseInMemoryDatabase与UseInternalServiceProvider一起使用。没有配置数据库提供商

时间:2016-11-14 10:10:03

标签: c# entity-framework asp.net-core entity-framework-core

我在使用EntityFrameworkCore时无法注入自定义IAsyncQueryProvider。更准确地说,在使用提供的内存数据库功能时,我无法注入提供程序。使用默认提供程序(SqlServer),一切正常。

这是我的全球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,只是通过请求。其中没有包含逻辑。

当我运行测试时,我将webhost配置为使用不同的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:尚未为此DbContext配置数据库提供程序。可以通过覆盖DbContext.OnConfiguring方法或在应用程序服务提供程序上使用AddDbContext来配置提供程序。如果使用AddDbContext,那么还要确保您的DbContext类型在其构造函数中接受DbContextOptions对象,并将其传递给DbContext的基础构造函数。

APIContext已正确定义:

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

UseInternalServiceProvider删除TestStartup可以正常工作 - 但是,我不希望我的测试达到实际的数据库。此外,我希望UseInMemoryDatabase能够自动将依赖项注入服务提供者 - 因为它本身完全正常。

错误令人困惑,因为内存数据库 是我想要使用的提供程序。

2 个答案:

答案 0 :(得分: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);
    }
}

答案 1 :(得分:-1)

单击 -> 解决方案资源管理器中的属性文件夹。 打开 -> launchSettings.json 文件 api/TodoItems

“个人资料”:{ “IIS Express”:{ "commandName": "IISExpress", “launchBrowser”:真, "launchUrl": "swagger", “环境变量”: { "ASPNETCORE_ENVIRONMENT": "开发" } },

“个人资料”:{ “IIS Express”:{ "commandName": "IISExpress", “launchBrowser”:真, "launchUrl": "api/TodoItems", “环境变量”: { "ASPNETCORE_ENVIRONMENT": "开发" } },