Why I should use AddScoped()
for my repositories or services? Why not AddSingleton()
?
I know about differences between them, but dont understand why I shouldn't use singleton instances to avoid creating new objects for each requests.
Can you explain it (preferably with examples :) )?

- 108
- 1
- 7
-
AddSingleton() is a singleton mode, it is unique in the entire container, so when the program is running, its instance is unique. AddScoped() is unique in a specific domain, and the domains do not affect each other. – Qing Guo May 13 '22 at 05:26
-
Example: If you are using Entity Framework as your ORM then you can't register the DbContext as Singleton since it is not thread-safe. So you have to register it as transient via AddDbContext. – Peter Csala May 13 '22 at 05:48
-
It's all about storing request-specific state. There are two models for storing request-specific state. In [one model](https://blogs.cuttingedge.it/steven/p/ccm/) you capture runtime data in variables of objects in your graph. This requires using a Scoped lifestyle. But there's [another model](https://blogs.cuttingedge.it/steven/p/acm/) that keeps runtime data outside the resolved objects and stores it as ambient data. This allows objects to be registered as singleton, because they themselves don't have any state. – Steven May 13 '22 at 07:46
2 Answers
As you said, you know the difference so I won't get into that.
The reason you don't want addSingleton for your repositories or services is because typically your repositories and services are considered "business logic" and "persistence logic". And in your business logic you might have some class level variables that are getting set. Those properties would not be different for every request, they would be shared across the requests. (think of them like static properties).
Example:
Imagine you have a user service that sets the username of the user making the request as a class level variable.
Singleton logic:
Now imagine Bob makes a request to the api. The username would be set to "Bob" . Now imagine at the same time, John makes a request to the api. The username would get set to "John". But because the user service is a singleton, both John and Bob are sharing the same instance, meaning Bob's username would also be set to "John".
Scoped logic:
Imagine the exact same scenario as above, but this time when John makes a request, it does not override bobs username, because they are different instances.

- 578
- 3
- 11
The below three methods define the lifetime of the services,
AddTransient Transient lifetime services are created each time they are requested. This lifetime works best for lightweight, stateless services.
AddScoped Scoped lifetime services are created once per request.
AddSingleton Singleton lifetime services are created the first time they are requested (or when ConfigureServices is run if you specify an instance there) and then every subsequent request will use the same instance.
Imagine you have a aspnet-core project.
If you want to create an object only once during the program's runtime and use the same object each time, you should use addingingleton.
If you want an object to be new() again every time it receives a request while the program is running, you should use addscoped().
If you want an object to new() every request and response, you must use AddTransient.

- 72
- 1
- 8
-
In the typical case the definition for Scoped is correct :) *Technically speaking* Scoped services are not created once per request but once per service scope. It just happens that ASP.NET Core creates a scope for each request. But you could also create your own scopes in the application, which would get different instances even though it was during the same request. – juunas May 13 '22 at 05:50
-