In Startup.cs it's possible to control dependency injection lifecycle using transients and singletons. However it's unclear how the lifecycle works when using .AddDBContext like so services.AddDbContext<DatabaseContext>(...);
Each controller uses this dependency by initialising it only once in the constructor and is reused throughout by the controller functions.
Is the context initialised for each request or is there a possibility this context being shared between user sessions resulting in bad state?
Note: duplicate question does not address if context is being shared between user sessions.
services.AddDbContext<>(...); registers your DbContext with Scoped lifetime. That means a new instance is created for every single request. No need to worry it would be shared with other connections.
Related
I am very new to Autofac dependency injection and I got these questions related to my project. I have gone through many articles but I am not getting a clear picture on some of the questions I have. Mine is a service application on .Net REST API. I am doing instance registration in App_Start module as shown below.
private static IContainer RegisterServices(ContainerBuilder builder)
{
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterType<DCLMessengerContext>()
.As<DbContext>()
.ExternallyOwned()
.InstancePerLifetimeScope();
builder.RegisterType<DbFactory>()
.As<IDbFactory>()
.ExternallyOwned()
.InstancePerLifetimeScope();
builder.RegisterType<UnitOfWork>()
.As<IUnitOfWork>()
.InstancePerLifetimeScope();
builder.RegisterGeneric(typeof(EntityBaseRepository<>))
.As(typeof(IEntityBaseRepository<>))
.InstancePerLifetimeScope();
builder.RegisterType<PersonServiceClient>()
.As<IPerfService>()
.InstancePerLifetimeScope();
builder.RegisterType<PagingServiceContractClient>()
.As<PagingServiceContract>()
.InstancePerLifetimeScope();
builder.RegisterType<MessageService>()
.As<IMessageService>()
.InstancePerLifetimeScope();
Container = builder.Build();
return Container;
}
My service layer is "MessageService" and there I am performing all the DB and other integration operations and getting the instances through constructor injection. These are the questions I have around this implementation.
I am using InstancePerLifeTimeScope for all my registrations. Is this is the right approach? After the life cycle of each controller request (http request), will these instances will be automatically disposed?
Do we need to manually implement any Dispose operation on any of these instances? ( I don’t have any unmanaged objects in my code)
From the service method, I need to create a fire&forget thread as well using Task.Run(). What is the best approach to supply instances to this fire&forget thread? If I use InstancePerLifeTimeScope, I can see that new thread also getting the same instances that available through the service class so I am just confused when these instances will be disposed?
When you resolve the instance per lifetime scope component, you get a
single instance per nested scope
So if you are using them in controllers. You will have one object for per request and they will be disposed. But if you resolve them in a singleton object they wil live with this object.
Is this is the right approach?
It depends what you need. If you need singleton object, it's not. If you just want to use this service in request scope use instanceperrequest it's better.
Autofac automatically calls dispose for IDisposable objects. If you
need dispose method, implement it. It's not related with autofac.
If you use another thread resolve objects in this thread. Otherwise when request disposed your objects will be disposed and your thread will be fail. Check this.
To be specific, I need to create an array variable that will be used for caching data, but I don't want to use ZF2 Cache Adapter.
I've tried to create a invokable class that would be used to instantiate object of my class that contains methods for setting and getting values from array that is also defined as a property of that class. As far as I understand, service manager treats all services as shared by default, which is supposed to create only one instance off my class when I get the service by service manager method get for the first time. But this doesn't work, if I get that service in different actions in my Controller class, which is what I need to do. So, how am I supposed to achieve this effect? Create an object that is available application-wide?
I had this kind of problem with managing a cart.
My cart is modeled by a CartManager, which is a unique instance for a user (session) and until paiement (cart is persisted in database).
I register my CartManager as a Service to build the first instance, this instance is built during an event handler attached on MvcEvent::EVENT_ROUTE, once built I override the CartManager service with my Instance, this way wherever I call the service, my first instance is served.
Then I persist (session or database) my Instance in an other event handler attached on MvcEvent::EVENT_FINISH.
All the event handlers are attached in Module::onBoostrap()
Is there a way to make Autofac to always resolve types in a new lifetimescope?
ie.
Container.Resolve<MyHandler>().Whatever();
Now i have to do like this:
Container.BeginLifetimeScope().Resolve<MyHandler>().Whatever();
It would be nice to be able to inject MyHandler into a class and know that MyHandler is it own scope.
Autofac does not provide a way to automatically start a new lifetime scope per component resolution.
Creating a lifetime scope is actually a process you need to control very tightly. Lifetime scopes not only help the scoping of component resolution, but also manage the deterministic disposal of components you resolve. From a memory management perspective, you shouldn't just fire up lifetime scopes without also disposing of them when you're done. Failing to dispose your created scopes can very easily cause a memory leak.
This is why you always see BeginLifetimeScope in a using statement or in a very tightly integrated scenario like ASP.NET request lifetime - so you can start a scope at a known spot and be sure to end/dispose of it. Child lifetime scopes are not automatically disposed for you once they're created - it's up to you to do that cleanup.
The Autofac wiki has some good information on lifetime scopes here.
I have the need to check if an instance of some interface has already been created by structuremap. I have tried ObjectFactory.GetInstance() but this creates a new instance of T when called and a concrete instance of T does not exist. I just want to check if an instance of T has already been created (not to create a new). I need this to force the creation of instances through a certain class).
You should be able to do this using:
ObjectFactory.Model.InstancesOf<IYourInterface>().First().ObjectHasBeenCreated();
Note, this only works for instances with Singleton, HttpContext or Hybrid lifecycle.
You cannot ask StructureMap if it has already created an instance of an interface.
However, it does have many lifecycle management features that allow it to control whether it creates a new instance, or returns a cached instance that it previously created.
You can tell StructureMap to make an instance HttpContextScoped, so that it returns the same instance for a given HTTP request.
It sounds like what you really want to know is how to handle NHibernate sessions in a web application with StructureMap. Try:
http://trason.net/journal/2009/10/7/bootstrapping-nhibernate-with-structuremap.html
we are developing ASP.NET web application with cEF ode first. What/Where is the best possible place to create/dispose DBContext for a request? I have only a single context and am not using any DI containers. Currently i have multiple methods to call per request and each creates context of their own. How do i say, something like.. GetContextforRequest() and use it for the request and dispose it when request is processed?
Thanks in advance
What't your looking for in terms of having 1 context per request is a pretty good way to use contexts, in that you reduce the overhead of creating them. You can create new context on BeginRequest, and store it in HttpContext.Current.Items, and on EndRequest dispose of it.
You can then create a . GetContextforRequest() method to encapsulate the fetch from HttpContext.Current.Items
I would however suggest looking at using a DI container. most of them have helpers to aide with creating and disposing of objects per request.
Edit
The benefit of having a Context open for the duration of a Request is that you can take advantage of 1st level caching. This is where objects are cached for the lifetime of the Context. So say you have a table called User containing a bunch of Users, and you call context.Set().ToList() twice in the same request, the first call will fetch the data from the database, the second call will retrieve it from the 1st level cache.