Eligiendo el DbContext Lifetime correcto

AddDbContext, AddDbContextPool, AddDbContextFactory, AddPooledDbContextFactory — una forma simple de decidir cuál usar en EF Core.

Es más fácil de lo que parece terminar usando el DbContext lifetime equivocado sin darse cuenta.

EF Core ofrece cuatro formas de registrarlo:

  • AddDbContext()
  • AddDbContextPool()
  • AddDbContextFactory()
  • AddPooledDbContextFactory()

Y la pregunta es siempre la misma: ¿cuál se supone que debo usar?

Antes de elegir uno, hay una sola pregunta que vale la pena hacerse: ¿dónde se va a ejecutar este código? La respuesta suele indicar qué método de registro corresponde.


#AddDbContext()

Se usa cuando el código corre dentro de un request HTTP típico.

Un request obtiene una instancia de DbContext. Eso es exactamente lo que necesita la mayoría de las aplicaciones web: simple, predecible y seguro.

CSHARP
builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(connectionString));

#AddDbContextPool()

Se usa cuando la API maneja un volumen alto de requests.

En lugar de crear una instancia nueva por cada request, reutiliza instancias de DbContext desde un pool, lo que reduce el overhead de allocation.

CSHARP
builder.Services.AddDbContextPool<AppDbContext>(options =>
    options.UseSqlServer(connectionString));

El pooling puede mejorar el throughput en el escenario correcto. Pero como toda optimización, conviene medir antes de adoptarla.


#AddDbContextFactory()

Se usa cuando el código corre dentro de background services, jobs programados, Task.WhenAll, o cualquier operación en paralelo.

Un DbContext no es thread-safe. Cada operación concurrente necesita su propia instancia, y la factory crea una nueva bajo demanda.

CSHARP
builder.Services.AddDbContextFactory<AppDbContext>(options =>
    options.UseSqlServer(connectionString));
CSHARP
public class ReportGenerator(IDbContextFactory<AppDbContext> factory)
{
    public async Task GenerateAsync()
    {
        await using var context = await factory.CreateDbContextAsync();
        // ...
    }
}

#AddPooledDbContextFactory()

Se usa cuando se necesitan instancias independientes de DbContext y, al mismo tiempo, aprovechar el pooling — ideal para procesamiento en background de alto throughput.

CSHARP
builder.Services.AddPooledDbContextFactory<AppDbContext>(options =>
    options.UseSqlServer(connectionString));

Combina la flexibilidad de una factory con el rendimiento de un pool.


#Ninguno es "mejor"

Ahí está el detalle que se pasa por alto fácilmente: estos cuatro métodos no están ordenados de peor a mejor. Están diseñados para modelos de ejecución distintos, y EF Core ofrece los cuatro para que el registro pueda ajustarse a cómo corre realmente el código.

Cuando la pregunta pasa a ser "¿dónde corre esto?" en lugar de "¿cuál es mejor?", la elección suele volverse obvia.

#ef-core #dotnet #dbcontext