Creación de DbContext en tiempo de diseño
Algunos de los comandos de EF Core Tools (por ejemplo, los comandos Migrations ) requieren que se cree una instancia derivada DbContext
en tiempo de diseño para recopilar detalles sobre los tipos de entidad de la aplicación y cómo se asignan a un esquema de base de datos. En la mayoría de los casos, es deseable que el DbContext
objeto creado se configure de forma similar a cómo se configuraría en tiempo de ejecución.
Hay varias formas en que las herramientas intentan crear el DbContext
:
Servicios de aplicación
Si el proyecto de inicio usa el host web de ASP.NET Core o el host genéricode .NET Core, las herramientas intentan obtener el objeto DbContext del proveedor de servicios de la aplicación.
Las herramientas intentan obtener primero el proveedor de servicios invocando Program.CreateHostBuilder()
, llamando a Build()
y accediendo a la propiedad Services
.
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)
{
}
}
Nota:
Al crear una nueva aplicación ASP.NET Core, este enlace se incluye de forma predeterminada.
El propio DbContext
y las dependencias de su constructor deben registrarse como servicios en el proveedor de servicios de la aplicación. Esto se puede lograr fácilmente teniendo un constructor en que DbContext
toma una instancia de DbContextOptions<TContext>
como argumento y usando el AddDbContext<TContext>
método.
Uso de un constructor sin parámetros
Si DbContext no se puede obtener del proveedor de servicios de aplicación, las herramientas buscan el tipo derivado DbContext
dentro del proyecto. A continuación, intentan crear una instancia mediante un constructor sin parámetros. Puede ser el constructor predeterminado si DbContext
está configurado mediante el método OnConfiguring
.
Desde una fábrica en tiempo de diseño
También puede indicar a las herramientas cómo crear dbContext mediante la implementación de la Microsoft.EntityFrameworkCore.Design.IDesignTimeDbContextFactory<TContext> interfaz: si se encuentra una clase que implementa esta interfaz en el mismo proyecto que el derivado DbContext
o en el proyecto de inicio de la aplicación, las herramientas omiten las otras formas de crear DbContext y usan el generador en tiempo de diseño en su lugar.
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);
}
}
Un generador en tiempo de diseño puede ser especialmente útil si necesita configurar de forma diferente para el DbContext
tiempo de diseño que en tiempo de ejecución, si el DbContext
constructor toma parámetros adicionales no están registrados en la inserción de dependencias, si no usa di en absoluto, o si por algún motivo prefiere no tener un CreateHostBuilder
método en la clase de Main
la aplicación ASP.NET Core.
Args
Tanto IDesignTimeDbContextFactory<TContext>.CreateDbContext como Program.CreateHostBuilder
aceptan argumentos de línea de comandos.
Puede especificar estos argumentos desde las herramientas:
dotnet ef database update -- --environment Production
El --
token dirige dotnet ef
a tratar todo lo que sigue como argumento y no intenta analizarlos como opciones. Los argumentos adicionales no utilizados por dotnet ef
se reenvieron a la aplicación.