ASP.NET DI开箱即用并递归地解析所有构造函数依赖项,这很棒。虽然有时您希望能够直接访问DI容器。我想知道是否有办法?也许是这样的:
IService service = Container.Instance.Resolve<IService>();
我在docs中没有找到任何东西(虽然我知道,我可以替换内置的DI框架)。
在大多数情况下,您不需要它,但有一些特定情况。在我的情况下,我需要在应用启动时使用IoC容器初始化我的EF DbContext,以启动应该像EF Core那样工作的自动迁移:
using (var context = new MyContext())
{
context.Database.Migrate();
}
我的上下文在容器中注册,但它位于一个单独的类库中。我不想直接称它为DbContextOptions
构造函数。
在问题得到更新并且很明显它正在进行EntityFramework Core迁移之后,ASP.NET核心团队就如何在应用程序启动期间正确解析DbContext
有一种半官方的方式。
默认情况下,DbContext
被注册为作用域服务,因此每个请求都会实例化一次。应用程序启动期间的问题是,目前还没有上下文,app.ApplicationServices
方法中只有Configure
可用,而ApplicationServices
提供程序实际上是解析单例(范围是每个范围的单例,应用程序范围与应用程序一样长)。
所以诀窍是首先创建一个范围,解决DbContext
,执行操作然后处理上下文(以及DbContext
)。
可以在音乐商店示例应用程序qazxsw poi和qazxsw poi中找到示例。
截至目前,这是解决它的唯一安全方式,不会导致任何问题,即处置对象异常。
另请注意,您可以执行此操作的最早点是使用here方法,因为只有IoC容器才构建完成。在here你只填充Configure
。
相关代码片段:
ConfigureServices
编辑:
有关此问题的其他资源:
IServiceCollection
问题,@ divega的初步提案。void Configure(IApplicationBuilder app)
{
//Populates the MusicStore sample data
SampleData.InitializeMusicStoreDatabaseAsync(app.ApplicationServices).Wait();
}
public static class SampleData
{
...
public static async Task InitializeMusicStoreDatabaseAsync(IServiceProvider serviceProvider, bool createUsers = true)
{
using (var serviceScope = serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
var db = serviceScope.ServiceProvider.GetService<MusicStoreContext>();
if (await db.Database.EnsureCreatedAsync())
{
await InsertTestData(serviceProvider);
if (createUsers)
{
await CreateAdminUser(serviceProvider);
}
}
}
}
}
(该问题的结束评论)