使用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
能够自动将依赖项注入到服务提供者中——因为它自己工作得很好。
错误是混乱的,因为在内存数据库是我想使用的提供者。
不幸的是,解决方案非常简单。然而,关于在内存数据库功能中使用依赖注入的文档似乎很少。它似乎是其中之一。希望这个问题能对未来不幸遇到这种情况的人有所帮助。
我下载了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"}},