AndyH
AndyH

Reputation: 447

.NET Core Singleton service instance in Web Controller

I am fairly new .NET, so pardon my ignorance, and I am trying to learning more .NET Core now.

I have, for instance, a user service which is used in a WebApi Controller. Is it safe to register the user service as a singleton, or do I need to register it as scoped? My concern is that if multiple users call the same endpoint, for instance /users/me, it might return each others information. Is that the case, or is it safe to use a singleton service to retrieve such data from the database? I get the user's Id from the http context, and use userService.FindById(userId) to retrieve the data. I can't seem to find this information from the lifecycle docs. Thanks

Upvotes: 0

Views: 785

Answers (1)

Chris Pratt
Chris Pratt

Reputation: 239460

Generally, no, it won't be an issue. Based on the simplistic description, there's no chance of cross-over. However, if you're doing some sort of caching or otherwise persisting user info to the class in any way (such as setting an ivar), you could have issues. Generally speaking, if aside from any dependencies you are injecting into the constructor, the class could otherwise be made static and still work, you're fine. If you're doing anything internally that would prevent making the class static, then there's a good chance you're leaking.

That said, if your service has dependencies on scoped services, it should be scoped itself. With something like a "users" service, there's a good chance you're going to be relying on something like an EF context or UserManager<TUser>, etc. Those are scoped, so with your service as a singleton, you'll be forced to employ the service-locator anti-pattern and you'll also likely be doing things inefficiently in general trying to work around the dependencies having a shorter lifetime than the service itself. It's best in such a scenario to make your service scoped, allowing you to injected scoped dependencies directly.

There seems to be a naive idea that the default or preferred lifetime should be singleton for things like services, repos, etc. In fact, the opposite is true: you should prefer scoped unless there's a good explicit reason to do otherwise. For example, if you're trying to coordinate some set of tasks across threads using something like SemaphoreSlim, that's a fairly obvious scenario that would require a singleton lifetime. Unless you're doing something like that truly requires a singleton lifetime, use a scoped lifetime instead.

Upvotes: 3

Related Questions