ASP.NET Core 2.0 service life time - c#

I have api application ,service & repository class library application . Service part i write business logic and repository only communicate for database. My question which type of dependency is best for repository and service .
services.AddScoped<ITicketRepository, TicketRepository>();
services.AddTransient<ITicketRepository, TicketRepository>();
services.AddSingleton<ITicketRepository, TicketRepository>();

Like always, it depends. My suggestion is the following:
Scoped: in my opinion, there can be two main reasons for using this:
Your dependency has a dependency which has a scoped lifetime. In this case, you cannot use singleton, but can use scoped or transient. Which one you should take is based on the other criteria.
Your dependency has some state which makes it unsuitable to be used in singleton scope, but it is heavyweight enough that you don't want to register it as transient. Another possibility is that, again, it cannot be used in singleton scope, but it is fine to share the same instance per request (scope) and you don't want to add the overhead of constructing new ones if two types depend on the same thing and both of them are used to serve a single request.
Transient: this is the simplest approach. Every time an instance of a dependency registered in this manner is required, a new instance is created. This is probably the most foolproof, but can cause serious overhead if its usage is not justified. #Tony Ngo pointed out in his answer, quoting from the official docs, that this works best for lightweight, stateless objects, but I'd argue that statelessness is a very good indicator that you may want to use singleton lifetime as statelessness guarantees that the same object can be used concurrently just fine. Whether you choose transient or singleton lifetime in this case really depends whether you care about such aspects of performance like GC cost, which is obviously much, much higher if you create a new instance every time such a dependency is required, even if you could avoid doing so. Having said that, transient is used by many developers in this scenario as well, probably due to its foolproofness, or simply because they tend to think about it as the default choice.
Singleton: the points above basically summarize this one: you can choose this when there is absolutely no reason to create a new instance of the dependency for each request (scope) or to use an other dependent instance. Note that like said before, you cannot use singleton lifetime when the type has a dependency which is registered as scoped.

Transient lifetime services (AddTransient) are created each time
they're requested from the service container. This lifetime works best
for lightweight, stateless services.
Scoped lifetime services (AddScoped) are created once per client
request (connection).
Singleton lifetime services (AddSingleton) are created the first time
they're requested (or when Startup.ConfigureServices is run and an
instance is specified with the service registration).
So depend on what you need you can choose correct liftetime you can view it more here

I am assuming your TicketRepository is depend on your EF Core DbContext and your
EF Core DbContext is by default registered as ScopedSerivce so here registering TicketRepository as SingletonService is out of consideration as because:
It's dangerous to resolve a scoped service from a singleton. It may cause the service to have incorrect state when processing subsequent requests.
For more details: Dependency injection in ASP.NET Core-Service lifetimes
Now you can choose between AddTransient<> and AddScoped<> where:
Transient lifetime services (AddTransient) are created each time they're requested from the service container. This lifetime works best for lightweight, stateless services.
Scoped lifetime services (AddScoped) are created once per client request (connection).

Related

.NET Inject transient into singleton

Suppose I have a singleton service that needs to receive other objects via constructor injection.
What should be the lifetime of these dependencies, they should also be added as singletons?
Are any drawbacks for injecting transient services into singleton objects? I am thinking that even they are transient they will be in memory until the app shuts down because they are injected into a singleton object.
How do we handle such cases?
This doc has some guidance on the matter: https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection#service-lifetimes
In general I think the standard guidance is to ensure dependencies are registered with longer lifetimes than dependents. If you break this model, you run the risk of causing bad state between requests.

which service lifetime to pick for service layer

Trying to understand which service lifetime best for service layer Transient or scoped(WHY).
I am looking for pros and cons of using scoped as service layers instead of transient. does Transient service works well with Database Transaction or keeping service layer as scoped is not a good thing to do.
Thanks
Usually, you should default to transient lifetimes. These are easy to understand and will generally discourage you from keeping state in your services. It’s also the most compatible lifetime with other services since it can be used from anywhere. So unless you have certain requirements, just choose transient by default.
Scoped services are good when you have expensive operations or temporary state that should be kept for the duration of the request. Database connections are a good example of that because a database connection is not super cheap and using a single connection for handling the single request of a single user (which isn’t happening concurrently) works pretty well. Other examples would be calculated things on top of the request data, e.g. data retrieved from external sources about the user (although here you might even consider a longer living cache).
If you aren’t creating your database connection yourself, chances are that you already have some service through which you will need to go in order to work with the database. This service is then hopefully already registered to be scoped service. An example for this is the DbContext from Entity Framework Core which will be registered as a scoped dependency by default.
If you consume such services, you can consume them from a transient service. Multiple (transient) services will just end up receiving the same instance. But that’s an implementation detail your services shouldn’t bother with. So the default suggestion still counts: Register the service as transient.
When deciding between transient and scoped, it’s also a good idea to consider the following question: Is the service resolve multiple times during the handling of a single request? Is there a problem creating a separate instance each time (e.g. is it an expensive operation)? Then choosing a scoped lifetime may help you.

ASP.NET Core - Repository dependency injection fails on Singleton injection

I am using SoapCore to create a web service for my ASP.NET Core MVC application.
I am using Entity Framework Core and a simple Repository pattern to get my DB data.
I am injecting my repository classes via .AddSingleton() in my Startup.cs:
services.AddSingleton<IImportRepository, ImportRepository>();
services.AddSingleton<IWebService, WebService>();
Since the EF DbContext is scoped I get an error when calling my web service:
Cannot consume scoped service 'App.Data.ApplicationDbContext' from
singleton 'App._Repository.IImportRepository'.
When I use .AddScoped() instead, it works fine.
I've read injecting scoped dependencies via a controllers/classes constructor is bad practice, since it "falls back" to be a singleton or behaves like one.
I wonder if there is another way to make it work with singletons or if this has some major draw backs in the long term (about 100-200 users will use the site) when using scoped injections in my controllers via the ctor?
Simply put, your go-to lifetime should be "scoped". You should only use a singleton or transient lifetime if you have a good reason to do so. For a singleton, that's stuff like managing locks or holding data that needs to persist for the lifetime of the application, neither of which applies to the concept of a repository. Repositories should be entirely disposable. The point is to persist to the database or to some other store, so they should not contain any data in their own right that needs to be persisted.
Long and short, your best bet here is to simply make your repo(s) scoped, so you can directly inject the context. As far as constructor injection goes, I'm not sure where you got the idea that that's a bad practice. It's in fact how dependency injection works in most cases, so you can't really have one without the other.
If you absolutely need to have a singleton, then your only option is the service locator antipattern. For that, you will inject IServiceProvider:
public class MyRepo
{
private readonly IServiceProvider _serviceProvider;
public MyRepo(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
...
}
Then, each time you need the context (that's important), you'll need to do:
using (var scope = _serviceProvider.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<MyContext>();
// do something with context
}
Scoped objects cannot be injected in to singleton objects. Its simple as this, singletons are created only once when the app is starting and used by all the subsequent requests. Scoped objected are created during each request and disposed at the end of the request. So there is no way for the previously created single object to know about the scoped objects creating during each request. So using scoped objects is not possible in singletons. But the the other way around is possible.
injecting scoped dependencies via a controllers/classes constructor
I don't think its a bad practice at all. If not how are you planing to do unit testing?
Also its not right to make DB context singleton. You will face cashing issues/data anomalies in parallel and subsequent requests. In my opinion DB context has to be scoped and all the objects that uses the db-context has to be scoped all the way up.
So in you case, make all the objects ImportRepository, WebService and DB Context all scoped.
Cheers,

In Simple Injector why is it an error for a singleton or scoped service to depend on a transient service

I'm using simple injector 3.0.4
I have a service that with a lifestyle of scoped dependent on a service which has a lifestyle of transient.
When I call container.Verify() I get a diagnostic error about lifestyle mismatch.
The transient service causing the issues is injected into other transient services so before I go ahead and make my whole project scoped I need to ask. Why is a dependency from a scope of any lifestyle to transient an issue? Transients are newed up fresh each time they are injected so nothing else can interfere with it. In essence the lifetime of a transient object is governed by the service it is injected into.
Also I have already read the documentation on this subject from here, and I do understand why you wouldn't want a singleton dependent on a scoped service for instance but surely a dependency on transient is always safe?
Transients are newed up fresh each time they are injected so nothing else can interfere with it.
Transients are newed up every time you request them from the container, but once they are injected into a component, they will stick around for as long as that component lives. So if the consuming component is a singleton, this means that it will drag along all its dependencies, making them practically singletons as well. This behaviour becomes obvious when you look at how you would typically implement dependency injection:
public class SomeComponent
{
private readonly ILogger logger;
private readonly IService service;
public SomeComponent(ILogger logger, IService service) {
this.logger = logger;
this.service = service;
}
}
As you can see, the dependencies are stored in private fields of the component, will cause them to stay alive for as long as SomeComponent lives and SomeComponent will keep using the same dependencies.
In essence the lifetime of a transient object is governed by the service it is injected into.
Exactly; a component's lifestyle will be at least as long as its consumer. However, a dependency can have multiple consumers with different lifestyles, making it really hard to see how long the dependency will live. When injected into consumer 1 it might live for the duration of the request, while another instance of that dependency, injected into consumer 2, will live for as long as the application does.
Just as scoped instances, transient registrations are typically not thread-safe; otherwise you would have registered them as singleton. Keeping transients alive for a longer period of time, can obviously cause concurrency bugs or bugs related to stale data. This is why Simple Injector disallows this by default and throws an exception.
You might be confused by how Autofac defines its lifestyles, compared to Simple Injector. Autofac does not contain a Transient lifestyle. Instead it has an InstancePerDependency lifestyle. Technically this is the same as transient, but the intent is very different. With InstancePerDependency you say: "This component is intended to live as long as its consumer, whatever that lifestyle might be". There might be cases where this makes sense, but by doing this you are actually ignoring the elephant in the room and I've seen the lack of detection to be a common source of bugs. In most cases, if you don’t care about a components lifestyle, it means it should be registered as singleton – not InstancePerDependency.
The reason that Simple Injector doesn't allow transients to be injected into scoped instances is because scoped instances as well can live for a long time (depending on the application) and you can't always assume that transients can safely be injected into scoped consumers.
In the end it is all about communicating the intent of your code. In case a component is stateless or thread-safe, you should register it as singleton. It it's not thread-safe, you register it as scoped or transient. This makes it clear to anyone who reads the configuration how he should handle such component AND it allows Simple Injector to detect any misconfigurations for you.
While Simple Injector detects misconfigurations for you, I came to the conclusion that your DI configuration can be simplified considerably when your system is designed around object graphs that consist purely of singleton components. I expressed these thoughts here. This will remove many of the complexities we face when working with dependency injection, and even exposes SOLID principles violation even more quickly than DI by itself already does.
before I go ahead and make my whole project scoped
That is something I would not advice to do. You would typically see that only some of the 'leaf components' in your application are scoped (such as DbContext). Those scoped components don't depend on many other components. The components that you write yourself should typically be stateless and don't need any caching. So in case making the object graphs singleton is (not yet) an option, I would typically make as much of the object graph transient, and only those few leaf components scoped. Since transients can safely depend on scoped instances, everything will work as expected.

Limit instance lifetime to a single iteration

I'm working on a web application that uses a couple of services to synchronize data with external resources. The application and the services share the same data layer and use Castle Windsor to implement IoC.
In the web application there is the a PerWebRequest lifestyle which limits the lifetime of an instance to the lifetime of a request. I want to use something similar in the services.
The services are triggered every once in a while to do the synchronization. I want the services and repositories in the datalayer to be singletons within the a single iteration of the service, similar to the PerWebRequest lifestyle in the web application.
What I've come up with is the concept of a Run. A run is a single invocation of the synchronization code within the service. That looks like this:
using( _runManager.Run() )
{
var sync = _usageRepoFactory.CreateInstance();
sync.SynchronizeUsage();
}
The implementation of IRun will release all instances with the PerRunLifeStyle resolved since it's creation when it is disposed, at the end of the using block.
This code looks quite clean, but I wonder if there is a better way of doing this. I have tried using child containers but found these rather 'heavy' after profiling the solution.
Any feedback is welcome. If needed I can post the IRun implementation as well.
Update
Based on the comments I've cleaned up the code a bit. I've introduced a new service IRunManager which is basically a factory for IRun. I've also started using a factory to get rid of the ServiceLocator invocation.
Take a look at this contextual lifestyle

Categories