Ciclos de vida de servicios: Transient, Scoped, Singleton
Aprenda cómo los ciclos de vida Transient, Scoped y Singleton afectan a la creación, el uso compartido y la eliminación de objetos.
Ciclos de vida de servicios: Transient, Scoped, Singleton es una lección gratuita de C# Academy en CoddyKit. Esta es la lección 2 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de C# Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de C# Academy incluye 4 lecciones en total.
Por qué importan los ciclos de vida
El ciclo de vida de un servicio controla cuánto tiempo vive una instancia y cuántas instancias se crean. Elegir el ciclo de vida incorrecto provoca errores sutiles, como filtraciones de datos entre solicitudes o una creación excesiva de objetos.
Transient: una instancia nueva cada vez
Los servicios Transient se crean desde cero cada vez que se solicitan al contenedor. Úselos para servicios ligeros y sin estado, en los que compartir el estado podría ser peligroso.
builder.Services.AddTransient<IEmailSender, SmtpEmailSender>();
// Each resolution creates a new instance:
// var a = sp.GetRequiredService<IEmailSender>(); // new
// var b = sp.GetRequiredService<IEmailSender>(); // new (different)Scoped: una vez por solicitud
Los servicios Scoped se crean una vez por ámbito; normalmente, una solicitud HTTP en ASP.NET Core. La misma instancia se comparte durante una solicitud, pero se crea una nueva para la siguiente.
builder.Services.AddScoped<AppDbContext>();
// Within a single HTTP request:
// Both resolve to the SAME AppDbContext instance
// -> consistent unit of work across the requestSingleton: uno durante toda la vida de la aplicación
Los servicios Singleton se crean una vez y se reutilizan durante toda la vida de la aplicación. Úselos para servicios costosos de crear y seguros para subprocesos, como las cachés de configuración.
builder.Services.AddSingleton<IMemoryCache, MemoryCache>();
// Or register a pre-built instance:
var config = new AppConfig { MaxRetries = 3 };
builder.Services.AddSingleton<IAppConfig>(config);Comparación de los tres ciclos
Una comparación rápida:
- Transient — una instancia nueva en cada solicitud; utilidades sin estado
- Scoped — una instancia por solicitud HTTP; DbContext, unidad de trabajo
- Singleton — una instancia durante toda la vida de la aplicación; cachés, configuraciones
El problema de la dependencia cautiva
Inyectar un servicio Scoped o Transient en un Singleton es un error habitual. El Singleton conserva una referencia al servicio de corta duración y hace que permanezca activo demasiado tiempo.
// BAD: Singleton captures a Scoped service
public class MySingleton
{
private readonly AppDbContext _db; // Scoped!
public MySingleton(AppDbContext db) => _db = db;
// _db is now stuck alive for the app's lifetime
}Detectar infracciones de ámbito
Active ValidateScopes para que el contenedor genere una excepción al iniciar si detecta una dependencia cautiva. Así podrá detectar los errores antes de que provoquen problemas de datos en producción.
builder.Host.UseDefaultServiceProvider(options =>
{
options.ValidateScopes = true; // detect captive deps
options.ValidateOnBuild = true; // fail fast at start
});Servicios Scoped fuera de una solicitud
Para resolver servicios Scoped en una tarea en segundo plano, cree un ámbito explícito mediante IServiceScopeFactory. Nunca resuelva servicios Scoped directamente desde el contenedor raíz.
public class MyWorker : BackgroundService
{
private readonly IServiceScopeFactory _factory;
public MyWorker(IServiceScopeFactory factory) => _factory = factory;
protected override async Task ExecuteAsync(CancellationToken ct)
{
using var scope = _factory.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
await db.Users.ToListAsync(ct);
}
}Servicios Transient desechables
Los servicios IDisposable de tipo Transient resueltos desde el contenedor raíz se mantienen registrados hasta que se desecha el contenedor, al cerrarse la aplicación. Resuélvalos dentro de un ámbito para liberar los recursos rápidamente.
// Correctly scoped transient disposable
using var scope = sp.CreateScope();
var svc = scope.ServiceProvider.GetRequiredService<MyDisposableService>();
await svc.DoWorkAsync();
// svc.Dispose() called when scope is disposedElegir el ciclo de vida adecuado
Una guía sencilla para decidir:
- ¿El servicio no tiene estado? → Transient
- ¿Depende de una solicitud, por ejemplo, de la identidad del usuario o de DbContext? → Scoped
- ¿Es seguro para subprocesos y costoso de construir? → Singleton
En la práctica: los tres ciclos de vida juntos
Una API web habitual registra distintos servicios con ciclos de vida adecuados para garantizar la corrección y el rendimiento.
builder.Services.AddSingleton<IConfiguration>(builder.Configuration);
builder.Services.AddSingleton<ICacheService, RedisCacheService>();
builder.Services.AddScoped<AppDbContext>();
builder.Services.AddScoped<IOrderRepository, OrderRepository>();
builder.Services.AddScoped<OrderService>();
builder.Services.AddTransient<IEmailSender, SendGridEmailSender>();Comprobación rápida
¿Qué problema se produce cuando un servicio Singleton conserva una referencia a un servicio Scoped?
Recapitulación: ciclos de vida de los servicios
Ideas clave:
- Transient: una instancia nueva cada vez; adecuado para servicios sin estado y ligeros
- Scoped: una instancia por solicitud; DbContext, repositorios, unidad de trabajo
- Singleton: una instancia durante toda la vida de la aplicación; cachés, configuraciones y utilidades seguras para subprocesos
- Nunca inyecte servicios de corta duración en servicios de mayor duración (dependencia cautiva)
- Use
IServiceScopeFactorypara resolver servicios Scoped en tareas en segundo plano
Preguntas frecuentes
¿La lección «Ciclos de vida de servicios: Transient, Scoped, Singleton» es gratis?
Sí — el texto completo de «Ciclos de vida de servicios: Transient, Scoped, Singleton» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de C# Academy, actualiza a CoddyKit PRO. El curso de C# Academy incluye 4 lecciones en total.
¿Qué aprenderé en «Ciclos de vida de servicios: Transient, Scoped, Singleton»?
Aprenda cómo los ciclos de vida Transient, Scoped y Singleton afectan a la creación, el uso compartido y la eliminación de objetos. Practicas C# Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar C# Academy?
No se requiere experiencia previa. C# Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 2 de 4.
¿Cuánto tiempo toma la lección «Ciclos de vida de servicios: Transient, Scoped, Singleton»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de C# Academy?
Sí. Cada lección de C# Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Fundamentos de los contenedores DI
- Ciclos de vida de servicios: Transient, Scoped, Singleton
- Inyección por constructor e interfaces
- Patrones Factory y Options