entity framework - optionsbuilder - ¿Qué incluye DbContextOptions cuando se invoca un nuevo DbContext?
dbcontextoptions connection string (2)
No estoy usando DI y simplemente quiero invocar un DbContext desde mi controlador. Estoy luchando para averiguar cuáles deberían ser las ''opciones''?
ApplicationDbContext.cs
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public DbSet<Gig> Gigs { get; set; }
public DbSet<Genre> Genres { get; set; }
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);
}
}
GigsController.cs
public class GigsController : Controller
{
private ApplicationDbContext _context;
public GigsController()
{
_context = new ApplicationDbContext();
}
public IActionResult Create()
{
var viewModel = new GigFormViewModel
{
Genres = _context.Genres.ToList()
};
return View(viewModel);
}
}
El problema se deriva en mi constructor GigsController:
_context = new ApplicationDbContext();
Me estoy equivocando porque necesito pasar algo a ApplicationDbContext. No hay ningún argumento dado que corresponda con el parámetro formal requerido ''opciones'' de ''ApplicationDbContext.ApplicationDbContext (DbContextOptions)''
Intenté crear un constructor predeterminado en ApplicationDbContext derivado de base (), pero tampoco funcionó.
En mi startup.cs, he configurado el ApplicationDbContext
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddMvc();
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
}
Así es como lo haría:
public class GigsController : Controller
{
private readonly IConfiguration _configuration;
private string _connectionString;
DbContextOptionsBuilder<ApplicationDbContext> _optionsBuilder;
public GigsController (IConfiguration configuration)
{
_configuration = configuration;
_optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>();
_connectionString = _configuration.GetConnectionString("DefaultConnection");
_optionsBuilder.UseSqlServer(_connectionString);
}
public IActionResult Index()
{
using(ApplicationDbContext _context = new ApplicationDbContext(_optionsBuilder.Options))
{
// .....Do something here
}
}
}
Recientemente, estaba migrando un conjunto de datos muy grande a la base de datos (alrededor de 10 millones) y una instancia de contexto se consumirá rápidamente toda mi memoria. Por lo tanto, tuve que crear una nueva instancia de contexto y disponer la anterior después de cierto umbral para liberar memoria.
Esta no es una solución elegante pero funcionó para mí.
Si realmente desea crear el contexto manualmente, entonces puede configure esta manera:
var optionsBuilder = new DbContextOptionsBuilder<ApplicationDbContext>();
optionsBuilder.UseSqlServer(Configuration.GetConnectionStringSecureValue("DefaultConnection"));
_context = new ApplicationDbContext(optionsBuilder.Options);
(La DbContextOptionsBuilder<ApplicationDbContext>
es el tipo de argumento de options
en services.AddDbContext<ApplicationDbContext>(options =>
). Pero en el controlador, no tiene acceso al objeto de Configuration
, por lo que tendría que exponerlo como un campo estático en Startup.cs
o use algún otro truco, lo cual es una mala práctica.
La mejor manera de obtener ApplicationDbContext
es obtenerlo a través de DI:
public GigsController(ApplicationDbContext context)
{
_context = context;
}
El contenedor DI se encargará de instanciar y eliminar ApplicationDbContext
. Tenga en cuenta que tiene todo configurado correctamente en Startup.cs
:
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
Eso es configurar DI, ¿por qué no usarlo?
Una nota más sobre el constructor predeterminado de DbContext
: En EF6 se hizo así: public ApplicationDbContext(): base("DefaultConnection") {}
. Luego, el objeto base usaría la clase estática System.Configuration.ConfigurationManager
para obtener la cadena de conexión llamada DefaultConnection
de web.config
. Los nuevos Asp.net Core y EF Core están diseñados para ser lo más desacoplados posible, por lo que no deben depender de ningún sistema de configuración. En su lugar, simplemente pasa un objeto DbContextOptions
: crear ese objeto y configurarlo es una preocupación independiente.