使用inmemorydatabase与UseInternalServiceProvider.没有配置数据库提供程序

本文关键字:数据库 程序 配置 inmemorydatabase UseInternalServiceProvider 使用 | 更新日期: 2023-09-27 18:17:51

我在使用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,简单地通过了请求。里面没有逻辑。

当我运行测试时,我配置web主机使用不同的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运行测试会产生以下错误:

系统。InvalidOperationException:没有为此DbContext配置数据库提供程序。提供程序可以通过覆盖DbContext来配置。方法或在应用程序服务提供者上使用AddDbContext。如果使用了AddDbContext,那么还要确保DbContext类型在其构造函数中接受DbContextOptions对象,并将其传递给DbContext的基本构造函数。

APIContext是正确定义的:

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

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

错误是混乱的,因为在内存数据库我想使用的提供者。

使用inmemorydatabase与UseInternalServiceProvider.没有配置数据库提供程序

不幸的是,解决方案非常简单。然而,关于在内存数据库功能中使用依赖注入的文档似乎很少。它似乎是其中之一。希望这个问题能对未来不幸遇到这种情况的人有所帮助。

我下载了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);
    }
}

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

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

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