使用UseInMemoryDatabase和UseInternalServiceProvider。未配置数据库提供程序。

9

我在使用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)
    {
    }
    ...
}

TestStartup 中删除 UseInternalServiceProvider 是正确的 - 但是,我不希望我的测试命中实际数据库。此外,我期望 UseInMemoryDatabase 自动将依赖项注入到服务提供程序中 - 因为它本身可以完美地工作。
这个错误很令人困惑,因为内存数据库就是我想要使用的提供程序。
2个回答

14

不幸的是,解决方案非常简单,但是关于如何在使用内存数据库功能时使用依赖注入的文档似乎很少。似乎只能选择其中一种方式。希望这个问题能够为将来不幸遇到此类问题的人提供帮助。

我下载了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
{btsdaf} - Jeremy Thompson
{btsdaf} - Rob
可能与您遇到的问题相关的是这个问题或者这个问题 - Rob
{btsdaf} - Rob
1
{btsdaf} - Jeremy Thompson
{btsdaf} - Rob

-6

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

"profiles": { "IIS Express": { "commandName": "IISExpress", "launchBrowser": true, "launchUrl": "swagger", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } },

"profiles": { "IIS Express": { "commandName": "IISExpress", "launchBrowser": true, "launchUrl": "api/TodoItems", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } },


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接