ASP.NET Core 2 + Get instance of db context

I am trying to get an instance of DbContext (so that I can do some extra work when starting with it), I get the following error when trying to get an instance in the Configure method:

System.InvalidOperationException: "Cannot resolve the limited service" MyApp.Data.MyDbContext "from the root provider.

public void ConfigureServices(IServiceCollection services) { services.AddDbContext<MyDbContext>( options => options.UseSqlServer(Configuration.GetConnectionString("MyDbContext"))); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { var dbContext = app.ApplicationServices.GetService(typeof(MyDbContext)) as MyDbContext; } 

I can access the instance of the fine DbContext through the controller, etc.

+15
source share
2 answers

Paul Hales's comment is correct, but this method works better in .NET Core 1.0.

In ASP.NET Core 2.0, it is usually a bad idea to run any database configuration in Startup.cs . This is due to the fact that if you perform any migrations from the CLI or Visual Studio, it will start all Startup.cs and try to start your configuration, which will fail. Of course, if you are not using Entity-Framework, then this is not a problem, but it is not yet recommended for use in version 2.0. Now it is recommended to do this in Program.cs .

For example, you can create an extension method IWebHost that will run any necessary configuration.

 public static IWebHost MigrateDatabase(this IWebHost webHost) { var serviceScopeFactory = (IServiceScopeFactory)webHost.Services.GetService(typeof(IServiceScopeFactory)); using (var scope = serviceScopeFactory.CreateScope()) { var services = scope.ServiceProvider; var dbContext = services.GetRequiredService<YourDbContext>(); dbContext.Database.Migrate(); } return webHost; } 

And then in Program.cs you can call this method before starting it.

 public static void Main(string[] args) { BuildWebHost(args) .MigrateDatabase() .Run(); } 
+26
source

Just to add to @Travis's excellent answer, the preferred Main method syntax has changed a bit compared to Core 2.1 and now the Main method now has CreateWebHostBuilder instead of BuildWebHost .

The revised code for invoking the extension method is shown below.

NB: order is important here, the Build method returns WebHost , which extends the extension method, so you need to call the migrate method after Build() and before Run() ):

 public static void Main(string[] args) { CreateWebHostBuilder(args) .Build() .MigrateDatabase() .Run(); } 

There is more than one DbContext in our project, so I changed the extension method to a universal method that can accept any type of DbContext :

 public static IWebHost MigrateDatabase<T>(this IWebHost webHost) where T:DbContext { var serviceScopeFactory = (IServiceScopeFactory)webHost .Services.GetService(typeof(IServiceScopeFactory)); using (var scope = serviceScopeFactory.CreateScope()) { var services = scope.ServiceProvider; var dbContext = services.GetRequiredService<T>(); dbContext.Database.Migrate(); } return webHost; } 

Then you can combine calls to transfer different contexts:

 CreateWebHostBuilder(args) .Build() .MigrateDatabase<ApiAuthDbContext>() .MigrateDatabase<MainDbContext>() .MigrateDatabase<SomeOtherDbContext>() .Run(); 
0
source

Source: https://habr.com/ru/post/1271238/


All Articles