Services that are registered as Transient  are always different . That is, for each service call, a new instance of the object is created and provided to the DI .

Services that are registered as Scoped  provide one object to the DI  for each request .

Services that are registered as Singleton  are provided to the DI  in the first request of an object of the desired class , and in subsequent requests the same object is provided to the DI  .

To show the difference in performance between these lifetimes, consider a simple interface that has a GUID  property , and the class that inherits from this interface initializes the GUID  property in its constructor . Here are three interfaces named IOperationTtansient , IOperationScoped   and   IOperationSingleton  , each of which inherits from IOperation  . Then we register all four interfaces with different lifetimes and the difference between these lifetimes will be shown.

public interface IOperation
{
    Guid OperationId { get; }
}

public interface IOperationTransient : IOperation
{
}

public interface IOperationScoped : IOperation
{
}

public interface IOperationSingleton : IOperation
{
}

In the following, we will implement the class that inherited from these interfaces as follows

public class Operation : IOperationTransient, IOperationScoped, IOperationSingleton
{
    Guid _guid;
    public Operation()
    {
        _guid = Guid.NewGuid();
    }

    public Guid OperationId => _guid;
}

In the following , we will implement a class to show the difference between Scoped  and Transient  , which only receives services from the constructor and performs the initial value.

public class OperationService
{
    public IOperationTransient TransientOperation { get; }
    public IOperationScoped ScopedOperation { get; }
    public IOperationSingleton SingletonOperation { get; }

    public OperationService(IOperationTransient transientOperation,
        IOperationScoped scopedOperation,
        IOperationSingleton singletonOperation)
    {
        TransientOperation = transientOperation;
        ScopedOperation = scopedOperation;
        SingletonOperation = singletonOperation;
    }
}

And then we register the classes in DI.

services.AddScoped<IOperationScoped, Operation>();
services.AddSingleton<IOperationSingleton, Operation>();
services.AddTransient<IOperationTransient, Operation>();
services.AddTransient<OperationService, OperationService>();

Then we receive the services in the controller via DI  and in the view we show the GUID  value .

public class HomeController : Controller
{
    private readonly OperationService _operationService;
    private readonly IOperationTransient _transientOperation;
    private readonly IOperationScoped _scopedOperation;
    private readonly IOperationSingleton _singletonOperation;

    public HomeController(OperationService operationService, IOperationTransient transientOperation, IOperationScoped scopedOperation, IOperationSingleton singletonOperation)
    {
        _operationService = operationService;
        _transientOperation = transientOperation;
        _scopedOperation = scopedOperation;
        _singletonOperation = singletonOperation;
    }

    public IActionResult Index()
    {
        ViewBag.Transient = _transientOperation;
        ViewBag.Scoped = _scopedOperation;
        ViewBag.Singleton = _singletonOperation;
        ViewBag.Service = _operationService;
        return View();
    }
}

View code

@{
    IOperationTransient operationTransient = (IOperationTransient)ViewBag.Transient;
    IOperationScoped operationScoped = (IOperationScoped)ViewBag.Scoped;
    IOperationSingleton operationSingleton = (IOperationSingleton)ViewBag.Singleton;
    OperationService operationService = (OperationService)ViewBag.Service;
}
<div>
    <p>Scoped : @operationScoped.OperationId</p>
    <p>Transient : @operationTransient.OperationId</p>
    <p>Singleton : @operationSingleton.OperationId</p>
</div>

<p>Operation Service</p>
<div>
    <p>Scoped : @operationService.ScopedOperation.OperationId</p>
    <p>Transient : @operationService.TransientOperation.OperationId</p>
    <p>Singleton : @operationService.SingletonOperation.OperationId</p>
</div>

Finally, the following output will be shown in the view.

First request:

Scoped : cc0de4ac-0aaf-4e18-8a66-7c9672384f7b

Transient : 853f0faa-658e-4d9e-8288-99656636a96d

Singleton : 94e426e4-ec53-4665-949c-07eaf2f76dad

Operation Service

Scoped : cc0de4ac-0aaf-4e18-8a66-7c9672384f7b

Transient : 11e27e2e-1ecf-4fb7-b90f-6aace02121a4

Singleton : 94e426e4-ec53-4665-949c-07eaf2f76dad

Second request:

Scoped : d9f085f5-f72f-4eea-bf70-d490a602e80d

Transient : 11bab21a-032e-4eb5-8d5f-fd86ea19a640

Singleton : 94e426e4-ec53-4665-949c-07eaf2f76dad

Operation Service

Scoped : d9f085f5-f72f-4eea-bf70-d490a602e80d

Transient : 12f7a9a6-a38f-4abd-aef3-9cef25bb2732

Singleton : 94e426e4-ec53-4665-949c-07eaf2f76dad

The class that is registered as Singleton  is initialized in the first request and shows the same  value in subsequent requests .

But the class that is registered as Scoped  type shows a new value for each request .

And in the class that is registered as Transient  , it displays a new value for each class request .

 In this example, each service is called twice via DI. Once in the controller and once in the OperationService  class, but Scoped shows only one value per request, but Transient shows a new value for each call.

Powered by Froala Editor

Comments