Difference between AddTransient, AddScoped and AddSingleton in .NET Core

Updated on: May 26, 2021

.NET Core provides built in Dependency Injection, In most of the cases, we create Interfaces and inherit those interfaces into our actual class implementation, to declare the Dependency in .NET Framework we used to add third party tool like UnityContainer, but in .NET Core, we have inbuilt Services such as AddSingleton(), AddScoped() and AddTransient() to declare the dependency between classes, following article helps you to understand the difference between AddSingleton, AddScoped and AddTrasient:

AddSingleton vs AddScoped vs AddTransient in .NET Core:

AddSingleton:

With Singleton, an new instance is created when first time the service is requested and the same instance is used for all the request, even for every new http request it uses the same reference. It is like static where you get the same value of the property even if property accessed from different instance. See the below example to understand more on AddSingleton()

AddScoped:

With Scoped, a new instance is created for every new http request, but during http request, it uses the same reference for all the instances. See the below example to understand more on AddScoped().

AddTransient:

With transient, new instance is created for every request. See the below example to understand more on AddTransient()

Example of AddSingleton(), AddScoped() & AddTransient()

Declare Interface for Singleton Service

  1. interface IRandomValueSingletonService
  2.     {
  3.         int GetRandomValue();

  4.     }

Declare Interface for Scoped Service

  1.     interface IRandomValueScopedService
  2.     {
  3.         int GetRandomValue();

  4.     }

Declare interface for Transient Service

  1.     interface IRandomValueTransientService
  2.     {
  3.         int GetRandomValue();
  4.     }

Define class which will implement all above interface

  1.     public class RandomValueService : IRandomValueSingletonService, IRandomValueScopedService, IRandomValueTransientService
  2.     {
  3.         private int randomValue = new Random().Next();
  4.         public int GetRandomValue() => randomValue;
  5.     }

Startup.cs  =>ConfigureServices() method in .NET Core: Add all the Services in the IServiceCollection at the start of the application in Startup.cs class. Here we are adding all the services which will be using Dependency Injection and will be injecting the services. In this example we are using View Page (Index.razor) to inject the Dependency, check the below code to see how to Inject the Services into Blazor View page.

  1.  public void ConfigureServices(IServiceCollection services)
  2.         {
  3.             services.AddRazorPages();
  4.             services.AddServerSideBlazor();
  5.             services.AddSingleton<IRandomValueSingletonService, RandomValueService>();
  6.             services.AddScoped<IRandomValueScopedService, RandomValueService>();
  7.             services.AddTransient<IRandomValueTransientService, RandomValueService>();
  8.         }

Index.razor (Blazor View Page): We are injecting the services and will be calling GetRandomValue() method through instances of the services.

  1. @page "/"
  2. @inject BlazorServerApp.Data.IRandomValueSingletonService singletonInstance1
  3. @inject BlazorServerApp.Data.IRandomValueSingletonService singletonInstance2
  4. @inject BlazorServerApp.Data.IRandomValueScopedService scopedInstance1
  5. @inject BlazorServerApp.Data.IRandomValueScopedService scopedInstance2
  6. @inject BlazorServerApp.Data.IRandomValueTransientService transientInstance1
  7. @inject BlazorServerApp.Data.IRandomValueTransientService transientInstance2

  8. <div style="float:left;padding:20px;border:1px solid;">
  9.     <h5>AddSingleton(), AddScoped(), AddTransient() Example</h5>
  10.     <table border="1" cellspacing="5" cellpadding="5">
  11.         <tr>
  12.             <td>Instance</td>
  13.             <td>Singleton</td>
  14.             <td>Scoped</td>
  15.             <td>Transient</td>
  16.         </tr>
  17.         <tr>
  18.             <td>Instance 1</td>
  19.             <td>@singletonRandomVal1</td>
  20.             <td>@scopedRandomVal1</td>
  21.             <td>@transientRandomVal1</td>
  22.         </tr>
  23.         <tr>
  24.             <td>Instance 2</td>
  25.             <td>@singletonRandomVal2</td>
  26.             <td>@scopedRandomVal2</td>
  27.             <td>@transientRandomVal2</td>
  28.         </tr>
  29.     </table>
  30.   </div>

  31. @code{
  32.     int singletonRandomVal1, singletonRandomVal2, scopedRandomVal1, scopedRandomVal2, transientRandomVal1, transientRandomVal2;

  33.     protected override void OnInitialized()
  34.     {
  35.         singletonRandomVal1 = singletonInstance1.GetRandomValue();
  36.         singletonRandomVal2 = singletonInstance1.GetRandomValue();
  37.         scopedRandomVal1 = scopedInstance1.GetRandomValue();
  38.         scopedRandomVal2 = scopedInstance2.GetRandomValue();
  39.         transientRandomVal1 =  transientInstance1.GetRandomValue();
  40.         transientRandomVal2 =  transientInstance2.GetRandomValue();
  41.     }
  42. }

Output:

As you can see in the above output, Instance 1 and Instance 2 values of Singleton Instance Random Values are Same.

Also for Scoped Instance, both the instance values are same, but for Transient, both the instance Random Values are different.

When we make new Http request to the same page (ie. Refresh the Page on the browser), then it will show the following output:

As you can see from the above 2 outputs, value of both the Singleton instance are same and even for every new http request values doesn't change.

For Scoped instance new values are assigned for new http request but for all the instance in that http request, values of service are same. 

In case of Transient, values are different for each instance and for every http request.