Fábrica de DbContext agrupada
En general, DbContext es un objeto ligero: crearlo y liberarlo no implica una operación de base de datos. Sin embargo, cada instancia configura varios servicios internos, y hacerlo continuamente puede pesar en escenarios de alto rendimiento. Para estos casos, EF Core puede agrupar (pool) las instancias del contexto:
- Al liberar el contexto, EF Core restablece su estado y lo guarda en un grupo interno.
- La siguiente vez que se solicita una instancia, se devuelve la del grupo en lugar de crear una nueva.
Así, el costo de configuración del contexto se paga una vez al iniciar la aplicación. Por eso Crono configura una fábrica de CronoDbContexto agrupada al arrancar. Cuando se solicita una instancia, la fábrica busca una libre en el grupo o crea una nueva y la devuelve al grupo al liberarse.
Por defecto, el tamaño máximo del grupo es 1024 instancias y se puede modificar en appsettings.json con BdContextoTamanioGrupo. Si se supera el tamaño, las nuevas instancias no se guardan y EF vuelve al comportamiento sin agrupación.
Uso habitual
Crono registra el CronoDbContexto como servicio con ámbito que internamente resuelve una instancia del grupo, y la devuelve al terminar la solicitud. Por eso, en general no necesitas llamar a CrearDbContext de IDbContextFactory<CronoDbContexto>: basta con inyectar CronoDbContexto.
Cuándo usar la fábrica directamente
Hay situaciones donde conviene resolver una instancia del grupo manualmente:
- En clases singleton, que no pueden tomar un servicio con ámbito por constructor. Se inyecta
IDbContextFactory<CronoDbContexto>(que es singleton) y se arrienda una instancia por unidad de trabajo:
public class MiSingletonServicio
{
private readonly IDbContextFactory<CronoDbContexto> _dbFabrica;
public MiSingletonServicio(IDbContextFactory<CronoDbContexto> dbFabrica)
{
_dbFabrica = dbFabrica;
}
public async Task HacerAsync()
{
using (var db = _dbFabrica.CreateDbContext())
{
// Unidad de trabajo aislada...
} // --> se devuelve la instancia al grupo
}
}
- Fuera del ámbito de una solicitud HTTP (por ejemplo, un sink de logs que resuelve un contexto periódicamente por timer).
- En procesos muy largos que cargan o escriben muchas entidades: como el rastreador acumula demasiadas entidades y el rendimiento se degrada, a veces conviene resolver una instancia nueva del grupo tras completar un lote, en vez de desasociar todas las entidades (ver Acceso a datos).