![Dependency Injection](/wp-content/uploads/2023/12/Dependency-Injection-3-768x432.png)
Service lifetimes: Transient, Scoped & Singleton in ASP.NET Core
Article to explore and understand how service lifetimes work in ASP.NET Core using dependency injection.
Service lifetimes define how to create and delete the services stored in the service container. You must choose a suitable durability for each service according to its characteristics and requirements.
Services can be registered with one of the following lifetimes:
Transient
Transient objects are always different, they are created if you request them from the service container.
Function better for lighter services and without status.
Scoped
Scoped objects are the same for a given request, but vary between requests.
Scoped is the default life of Entity Framework Core when you add AddDbContext.
Singleton
Singleton objects are the same for each request, they are created the first time they are requested, each subsequent request of the service implementation from the dependency injection container uses the same instance.
Because memory is not freed until the application is closed, consider using memory with a singleton service.
- Important: Do not resolve a Scoped service from a Singleton and be careful not to do so indirectly. Solve as follows:
- Resolve a singleton service from a Transient or Scoped service.
- Resolve a Scoped service from another Transient or Scoped service.
Getting Started
This is an example to show how service lifetimes work using dependency injection in ASP.NET Core
Installation
1. Install packages
Install-Package Microsoft.Extensions.DependencyInjection
Usage
1. Create class and interface “Operation”
public interface IOperation
{
string OperationId { get; }
}
public interface IOperationTransient : IOperation { }
public interface IOperationScoped : IOperation { }
public interface IOperationSingleton : IOperation { }
public class Operation : IOperationTransient, IOperationScoped, IOperationSingleton
{
public Operation()
{
OperationId = Guid.NewGuid().ToString()[^4..];
}
public string OperationId { get; }
}
2. Add services to the container
builder.Services.AddTransient<IOperationTransient, Operation>();
builder.Services.AddScoped<IOperationScoped, Operation>();
builder.Services.AddSingleton<IOperationSingleton, Operation>();
3. Injection and use in controller and middleware to see how values to get OperationId change according to service lifetime
_logger.LogInformation("Transient: " + transientOperation.OperationId);
_logger.LogInformation("Scoped: " + scopedOperation.OperationId);
_logger.LogInformation("Singleton: " + _singletonOperation.OperationId);
4. When you start the application, you see how “Transient” middleware changes with respect to controller. While Scoped and Singleton do not change.
info: Lifetimes.MyMiddleware[0]
Transient: cc44
info: Lifetimes.MyMiddleware[0]
Scoped: 5582
info: Lifetimes.MyMiddleware[0]
Singleton: d05c
info: DbContext.Controllers.DIController[0]
Transient: 8af0
info: DbContext.Controllers.DIController[0]
Scoped: 5582
info: DbContext.Controllers.DIController[0]
Singleton: d05c
5. In a new http request, you can see that “Transient” changes. “Singleton” doesn’t change. But “Scoped” changes compared to the first results, because it is a new request.
info: Lifetimes.MyMiddleware[0]
Transient: 42b0
info: Lifetimes.MyMiddleware[0]
Scoped: 839f
info: Lifetimes.MyMiddleware[0]
Singleton: d05c
info: DbContext.Controllers.DIController[0]
Transient: d512
info: DbContext.Controllers.DIController[0]
Scoped: 839f
info: DbContext.Controllers.DIController[0]
Singleton: d05c
Conclusion, “Transient” objects are always different. “Scoped” objects are the same for a given request, but vary between requests. And “Singleton” objects are the same for each request, they are created the first time they are requested.
Example code
GitHub: Service lifetimes: Transient, Scoped & Singleton in ASP.NET Core