Criação de DbContext no tempo de design

Alguns dos comandos de ferramentas de EF Core (por exemplo, os comandos de migração ) exigem DbContext que uma instância derivada seja criada em tempo de design para coletar detalhes sobre os tipos de entidade do aplicativo e como eles são mapeados para um esquema de banco de dados. Na maioria dos casos, é desejável que a DbContext criação criada seja configurada de forma semelhante a como ela seria configurada em tempo de execução.

Há várias maneiras pelas quais as ferramentas tentam criar DbContext :

Dos serviços de aplicativos

Se o seu projeto de inicialização usar o host do ASP.NET Core Web ou o host genérico do .NET Core, as ferramentas tentarão obter o objeto DbContext do provedor de serviços do aplicativo.

As ferramentas primeiro tentam obter o provedor de serviços invocando Program.CreateHostBuilder() , chamando Build() e acessando a Services propriedade.

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 void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
    }
}

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

Observação

Quando você cria um novo aplicativo ASP.NET Core, esse gancho é incluído por padrão.

A DbContext si mesmo e as dependências em seu Construtor precisam ser registradas como serviços no provedor de serviços do aplicativo. Isso pode ser facilmente obtido com um construtor no DbContext que usa uma instância de DbContextOptions<TContext> como um argumento e usando o AddDbContext<TContext> método.

Usando um construtor sem parâmetros

Se DbContext não puder ser obtido do provedor de serviços de aplicativo, as ferramentas procurarão o DbContext tipo derivado dentro do projeto. Em seguida, eles tentam criar uma instância usando um construtor sem parâmetros. Esse pode ser o construtor padrão se o DbContext for configurado usando o OnConfiguring método.

De uma fábrica de tempo de design

Você também pode informar as ferramentas sobre como criar seu DbContext implementando a Microsoft.EntityFrameworkCore.Design.IDesignTimeDbContextFactory<TContext> interface: se uma classe que implementa essa interface for encontrada no mesmo projeto que o derivado DbContext ou no projeto de inicialização do aplicativo, as ferramentas ignorarão as outras maneiras de criar o DbContext e usar a fábrica de tempo de design em vez disso.

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);
    }
}

Observação

Antes do EFCore 5,0, o args parâmetro não era usado (consulte esse problema). Isso é corrigido no EFCore 5,0 e quaisquer argumentos adicionais de tempo de design são passados para o aplicativo por meio desse parâmetro.

Uma fábrica de tempo de design pode ser especialmente útil se você precisar configurar o de DbContext forma diferente para o tempo de design do que no tempo de execução, se o DbContext construtor usar parâmetros adicionais não estiver registrado em di, se você não estiver usando di, ou se por algum motivo você preferir não ter um CreateHostBuilder método na classe do aplicativo ASP.NET Core Main .

Args

IDesignTimeDbContextFactory<TContext>.CreateDbContextE Program.CreateHostBuilder aceitam argumentos de linha de comando.

A partir do EF Core 5,0, você pode especificar esses argumentos nas ferramentas:

dotnet ef database update -- --environment Production

O -- token direciona dotnet ef para tratar tudo o que segue como um argumento e não tentar analisá-los como opções. Quaisquer argumentos extras não usados pelo dotnet ef são encaminhados para o aplicativo.