Замечательно, что ASP.NET DI работает нестандартно и рекурсивно разрешает все зависимости конструктора. Хотя иногда вы хотите иметь прямой доступ к контейнеру DI. Интересно, есть ли способ? Может быть, примерно так:
IService service = Container.Instance.Resolve<IService>();
Я ничего не нашел в документах (хотя я знаю , Могу заменить встроенный DI framework).
По большей части вам это не нужно, но есть некоторые специфические случаи. В моей ситуации мне нужно инициализировать мой EF DbContext с помощью контейнера IoC при запуске приложения, чтобы инициировать автоматические миграции, которые должны работать таким образом с EF Core:
using (var context = new MyContext())
{
context.Database.Migrate();
}
Мой контекст зарегистрирован в контейнере, но в отдельной библиотеке классов. И я не хочу называть это DbContextOptions конструктором напрямую.
Ответ 1 · рейтинг 3 · Tseng
После того, как вопрос был обновлен и стало ясно, что речь идет о миграции EntityFramework Core, есть полуофициальный способ от команды ASP.NET Core о том, как правильно разрешить DbContext во время запуска приложения.
По умолчанию DbContext зарегистрирован как служба с заданной областью действия, поэтому экземпляр создается один раз для каждого запроса. Уловка во время запуска приложения заключается в том, что еще нет контекста, и только app.ApplicationServices доступен в Configure методе, а поставщик ApplicationServices по существу разрешает синглтоны (область видимости - это одноэлемент для каждой области, а область действия приложения существует, пока работает приложение).
Таким образом, уловка состоит в том, чтобы сначала создать область видимости, разрешить DbContext, выполнить операции, а затем удалить контекст (и DbContext с ним).
Примеры можно найти в примере приложения MusicStore здесь и здесь .
На данный момент это единственный безопасный способ решить эту проблему, не вызывая проблем с исключениями удаленных объектов.
Также обратите внимание, что самое раннее, что вы можете сделать, это метод Configure, потому что только тогда был построен контейнер IoC. В ConfigureServices вы заполняете только IServiceCollection.
Соответствующие фрагменты кода:
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);
}
}
}
}
}
Изменить:
Дополнительные ресурсы по этой проблеме: