Creazione di DbContext in fase di progettazioneDesign-time DbContext Creation

Alcuni dei comandi degli strumenti di EF Core (ad esempio, i comandi delle migrazioni ) richiedono la creazione di un'istanza derivata in fase di DbContext progettazione per raccogliere informazioni dettagliate sui tipi di entità dell'applicazione e su come eseguono il mapping a uno schema del database.Some of the EF Core Tools commands (for example, the Migrations commands) require a derived DbContext instance to be created at design time in order to gather details about the application's entity types and how they map to a database schema. Nella maggior parte dei casi, è preferibile che il DbContext creato sia configurato in modo analogo a come verrebbe configuratoin fase di esecuzione.In most cases, it is desirable that the DbContext thereby created is configured in a similar way to how it would be configured at run time.

Esistono diversi modi in cui gli strumenti tentano di creare DbContext :There are various ways the tools try to create the DbContext:

Da servizi applicazioniFrom application services

Se il progetto di avvio usa il ASP.NET Core host Web o l' host generico .NET Core, gli strumenti tentano di ottenere l'oggetto DbContext dal provider di servizi dell'applicazione.If your startup project uses the ASP.NET Core Web Host or .NET Core Generic Host, the tools try to obtain the DbContext object from the application's service provider.

Per prima cosa gli strumenti tentano di ottenere il provider di servizi richiamando, Program.CreateHostBuilder() Build() quindi accedendo alla Services Proprietà.The tools first try to obtain the service provider by invoking Program.CreateHostBuilder(), calling Build(), then accessing the Services property.

public class Program
{
    public static void Main(string[] args)
        => CreateHostBuilder(args).Build().Run();

    // EF Core uses this method at design time to access the DbContext
    public static IHostBuilder CreateHostBuilder(string[] args)
        => Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(
                webBuilder => webBuilder.UseStartup<Startup>());
}

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
        => services.AddDbContext<ApplicationDbContext>();
}

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }
}

Nota

Quando si crea una nuova applicazione ASP.NET Core, questo hook è incluso per impostazione predefinita.When you create a new ASP.NET Core application, this hook is included by default.

La DbContext stessa e tutte le dipendenze nel costruttore devono essere registrate come servizi nel provider di servizi dell'applicazione.The DbContext itself and any dependencies in its constructor need to be registered as services in the application's service provider. Questa operazione può essere eseguita facilmente con un costruttore su DbContext che accetta un'istanza di DbContextOptions<TContext> come argomento e usando il AddDbContext<TContext> Metodo.This can be easily achieved by having a constructor on the DbContext that takes an instance of DbContextOptions<TContext> as an argument and using the AddDbContext<TContext> method.

Uso di un costruttore senza parametriUsing a constructor with no parameters

Se il DbContext non può essere ottenuto dal provider di servizi dell'applicazione, gli strumenti cercano il DbContext tipo derivato all'interno del progetto.If the DbContext can't be obtained from the application service provider, the tools look for the derived DbContext type inside the project. Tentano quindi di creare un'istanza usando un costruttore senza parametri.Then they try to create an instance using a constructor with no parameters. Può essere il costruttore predefinito se DbContext è configurato utilizzando il OnConfiguring metodo.This can be the default constructor if the DbContext is configured using the OnConfiguring method.

Da una factory della fase di progettazioneFrom a design-time factory

È anche possibile indicare agli strumenti come creare il DbContext implementando l' IDesignTimeDbContextFactory<TContext> interfaccia: se una classe che implementa questa interfaccia si trova nello stesso progetto dell'oggetto derivato DbContext o nel progetto di avvio dell'applicazione, gli strumenti ignorano le altre modalità di creazione del DbContext e usano invece la factory della fase di progettazione.You can also tell the tools how to create your DbContext by implementing the IDesignTimeDbContextFactory<TContext> interface: If a class implementing this interface is found in either the same project as the derived DbContext or in the application's startup project, the tools bypass the other ways of creating the DbContext and use the design-time factory instead.

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.EntityFrameworkCore.Infrastructure;

namespace MyProject
{
    public class BloggingContextFactory : IDesignTimeDbContextFactory<BloggingContext>
    {
        public BloggingContext CreateDbContext(string[] args)
        {
            var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();
            optionsBuilder.UseSqlite("Data Source=blog.db");

            return new BloggingContext(optionsBuilder.Options);
        }
    }
}

Nota

Prima di EFCore 5,0 il args parametro non è stato usato (vedere questo problema).Prior to EFCore 5.0 the args parameter was unused (see this issue). Questo problema è stato risolto in EFCore 5,0 e gli eventuali argomenti della fase di progettazione aggiuntivi vengono passati all'applicazione tramite il parametro.This is fixed in EFCore 5.0 and any additional design-time arguments are passed into the application through that parameter.

Una factory della fase di progettazione può essere particolarmente utile se è necessario configurare DbContext in modo diverso per la fase di progettazione rispetto al runtime, se il DbContext costruttore accetta parametri aggiuntivi non viene registrato in di, se non si usa o se per qualche motivo si preferisce non avere un BuildWebHost metodo nella classe dell'applicazione ASP.NET Core Main .A design-time factory can be especially useful if you need to configure the DbContext differently for design time than at run time, if the DbContext constructor takes additional parameters are not registered in DI, if you are not using DI at all, or if for some reason you prefer not to have a BuildWebHost method in your ASP.NET Core application's Main class.