Sto cercando di ottenere un'istanza di DbContext (in modo da poter eseguire un lavoro aggiuntivo all'avvio con esso), viene visualizzato il seguente errore quando si tenta di ottenere un'istanza nel metodo Configure:
System.InvalidOperationException: 'Impossibile risolvere il servizio con ambito' MyApp.Data.MyDbContext 'dal provider root.'
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;
}
Posso accedere a un'istanza della multa DbContext tramite il controller, ecc
Il commento di Paul Hiles è corretto ma quel metodo funziona meglio con .NET Core 1.0.
In ASP.NET Core 2.0 è generalmente una cattiva idea eseguire qualsiasi configurazione del database in Startup.cs
. Questo perché se si eseguono delle migrazioni dalla CLI o da Visual Studio, verrà eseguito tutto Startup.cs
e tenterà di eseguire la configurazione che non riuscirà. Naturalmente se non si utilizza Entity-Framework, questo non è un problema, ma non è ancora il modo consigliato di farlo in 2.0. Ora è consigliato farlo in Program.cs
.
Ad esempio è possibile creare un metodo di estensione di IWebHost
che eseguirà tutte le impostazioni necessarie.
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;
}
E poi in Program.cs
puoi quindi chiamare quel metodo prima di eseguirlo.
public static void Main(string[] args)
{
BuildWebHost(args)
.MigrateDatabase()
.Run();
}
Solo per aggiungere all'eccellente risposta di @Travis Boatman , la sintassi preferita del metodo Main
è leggermente cambiata dal Core 2.1 in poi e il metodo Main
predefinito ora ha CreateWebHostBuilder
invece di BuildWebHost
.
Il codice rivisto per chiamare il metodo di estensione è mostrato di seguito.
NB: l'ordine è importante qui, il metodo Build
restituisce un WebHost
, che è l'estensione del metodo di estensione, quindi è necessario chiamare il metodo migrate dopo Build()
e prima di Run()
):
public static void Main(string[] args)
{
CreateWebHostBuilder(args)
.Build()
.MigrateDatabase()
.Run();
}
Abbiamo più di un DbContext
nel nostro progetto, quindi ho modificato il metodo di estensione in un metodo generico che può accettare qualsiasi tipo di 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;
}
È quindi possibile concatenare le chiamate per migrare i diversi contesti:
CreateWebHostBuilder(args)
.Build()
.MigrateDatabase<ApiAuthDbContext>()
.MigrateDatabase<MainDbContext>()
.MigrateDatabase<SomeOtherDbContext>()
.Run();