Reason to use PerThreadLifetimemanager vs Transientlifetimemanager - c#

I use DI in constructors.
BaseShoppingCart is a service in which I set ShoppingCartId (used for cart items).
here is the constructor:
public BaseShoppingCart( HttpContextBase context, IRepository<TCart> cart ,IProductService productservice)
{
_context = context;
_cart = cart;
_productService = productservice;
ShoppingCartId = _context.Request.IsAuthenticated ? _context.User.Identity.Name : getSessionCartId();
}
If I set Transientlifetimemanager (by default) in DI container (Unity) no bugs are revealed.
If I set PerThreadLifetimeManager any user may get cart of another user! As I read from this article Why is PerThreadLifetimeManager used in this example? - thread is longer than request so second call of ShoppingCartController is this case may not invoke ctor of BaseShoppingCart. Instead existing BaseShoppingCart object (object of another user) is returned from container.
I need your opinions:
Do I understand this problem correcltly?
In which cases PerThreadLifetimemanager is useful insted of Transientlifetimemanager?
Thanks!

To isolate users (requests) create new child container per request and resolve services from child one. So, you can register your services with HierarchicalLifetimeManager and you'll get new instance for each user (request).
Here are good examples.
And I don't recommend to use PerThreadLifetimeManager if you don't know, what you actualy do.

Related

C# Autofac New Instance

I have a class "DependencyResolver" where I return instances of objects by hand. There I used "Activator.CreateInstance".
I wanted to change it so it uses autofac.
My function "Get" works fine:
public T Get<T>()
{
return _container.Resolve<T>();
}
But I also have a function "CreateNew" where I need a new instance:
public T CreateNew<T>()
{
return _container.Resolve<T>();
}
The Problem is that I always get the same instance.
My Registration looks like this:
var builder = new ContainerBuilder();
foreach (var dllFileName in DependencyMapping.GetAllDllFilenames())
{
builder
.RegisterAssemblyTypes(Assembly.LoadFile(Path.Combine(GetPathFromInstalledSys(), dllFileName)))
.AsImplementedInterfaces()
.SingleInstance();
}
_container = builder.Build();
So there is a place where I can control the behaviour: "SingleInstance" or "InstancePerDependency". But I dont know whether the user needs a new instance or not. Is there any way to change the behavior when "CreateNew" is called?
Lifetime scope (single instance, instance per dependency) is controlled at registration time, not resolve time. There's no way to change it. This is the case with all DI containers, not just Autofac. Part of the point of it is that the consumer shouldn't have to know what scope they want - they just ask for a thing and get it.
Consumers also generally shouldn't deal with disposal - things get disposed by the container.
Note what you have here is service location (client asks the container for a thing), not dependency injection (client takes dependencies in constructor and doesn't know about the container). While service location is sometimes required, generally try to avoid it if you can; it's not really much better than just calling new in your code.

When do dispose of a _db connection in Web API

I've been doing a lot of reading around garbage collecting and and using IDisposable to handle connections via entity framework. I understand that I should be disposing of resources as soon as I'm done with them but I haven't seen a lot of good examples around when exactly that call should be made and where from and want to ensure I'm handling this correctly.
Let's say I'm returning a basic inventory list from a web API call. My assumption is I should call my dispose method immediately after I get the list. Is this correct? For example's sake let's look at the below method that lives in the service layer:
public class ServiceLayer
{
private InventoryContext _db = new InventoryContext();
public List<Inventory> GetFullInventoryList()
{
var inventoryList = _db.Inventory.ToList();
_db.Dispose();
return inventoryList;
}
public Inventory GetInventoryRecordById(int id)
{
var inventoryRecord = _db.Inventory
.Where(y => y.Id == id)
.First();
_db.Dispose();
return inventoryRecord;
}
}
Is this the correct way to dispose of resources? If not, when should it be called? If it is correct, but not the appropriate way, what is the appropriate way?
Thanks!
There are several options available, but all of them follow a common rule: the owner of the context (the one who creates it) should also dispose it.
You can:
Create your context in a service method and dispose it in the same method:
public List<Inventory> GetFullInventoryList()
{
using (var _db = new InventoryContext())
{
return _db.Inventory.ToList();
}
}
Create your context in your service class but then you would need to make the class IDisposable and implement the dispose pattern . This is more complicated, so only use it if you need to call multiple service methods that each work with the database.
Use dependency injection to supply context to the controller. In such a case, the lifetime of the context is configured while registering it in the container, and the container will call dispose on your context (for example Autofac or Windsor do this, assuming you call dispose on the container or its life scope). You can use PerWebRequest lifestyle for this.

SignalR and ASP.NET Identity's UserManager class lifetime

In my MVC application, I user SignalR for communication between users. Basically, a client calls a method on the hub, which calls a method on a repository, which then saves the message to the database and the hub notifies the other client of the new message.
I had used the GetOwinContext() method during these calls from the client to get the current instance of UserManager and ApplicationDbContext, by using the GetUserManager<UserManager>() and Get<ApplicationDbcontex>() extension methods, respectively. However, I have noticed that calls from the same connection use the same context, which is, obviously, not a very good thing. I went ahead and changed my repository so it is like this now:
public XyzRepository() //constructor
{
db = ApplicationDbContext.Create(); //static method that generates a new instance
}
private ApplicatonDbContext db { get; set; }
private UserManager UserManager
{
get
{
return new UserManager(new UserStore<ApplicationUser>(db)); //returns a new UserManager using the context that is used by this instance of the repository
}
}
Since I reference the ApplicationUser objects using the UserManager (using FindByIdAsync(), etc, depending on the design), it is extremely important to use the context I currently work with for the UserStore of the UserManager's current instance. The repository is created once per request, which seems to apply to each SignalR calls as intended. While I have experienced no problems with this design so far, after reading about the issue (in this article), particularly this line:
"In the current approach, if there are two instances of the UserManager in the request that work on the same user, they would be working with two different instances of the user object.", I decided to ask the community:
Question: what is the preferred way to use ASP.NET Identity's UserManager class with SignalR, if it is imperative that I use the same instance of DbContext for my repository's methods that the UserManager's UserStore uses?
I think the preferred way is to use an Inversion of Control container and constructor-inject dependencies with some kind of lifetime scope. Here is another question that you might want to look into:
Using Simple Injector with SignalR
It is preferable that your DbContext instance live as long as the current web request. IoC containers have facilities that let you register DbContext instances with per web request lifetimes, but you need to set up the IoC container so that it can manage the construction of the Hub classes to achieve this. Some IoC containers (like SimpleInjector) will also automatically dispose of the DbContext at the end of the web request for you, so you don't need to wrap anything in a using block.
As for the UserManager, XyzRepository, etc, I think those can also have per-web-request lifetime, or even transient lifetimes. Ultimately, I don't see why you wouldn't be able to achieve something like this:
public class MyXyzHub : Hub
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly MessageRepository _messageRepository;
public MyXyzHub(UserManager<ApplicationUser> userManager,
MessageRepository messageRepository)
{
_userManager = userManager;
_messageRepository= messageRepository;
}
public void sendMessage(string message)
{
var user = _userManager.FindByIdAsync(...
_messageRepository.CreateAndSave(new Message
{
Content = message, UserId = user.Id
});
Clients.All.receiveMessage(message, user.Name);
}
}
If you wire up your IoC container the right way, then every time the Hub is constructed, it should reuse the same ApplicationDbContext instance for the current web request. Also with your current code, it looks like XyzRepository is never disposing of your ApplicationDbContext, which is another problem that an IoC container can help you out with.

AutoFac LifeTime: Force new instance in specific situation

I have the following configuration:
builder.Register<EntityContext>().As(
c=> {
var entityCtx = new EntityContext();
//snip snip: some config stuff
return entityCtx;
}).As<MyDbContext>().InstancePerLifetimeScope();
EntityContext obviously inherits from MyDbContext which again inherits from DbContext.
In my repository's constructor I'm usually using them as
...
public MyRepository(MyDbContext context) {...}
This ensures to have one ctx per http request which is what I want. But now I have the need that for a specific repository I want to have a different instance of the EntityContext than is normally being used.
How would you achieve that? The following came to my mind:
Another config where I use Register<EntityContext>()....As<DbContext>()...
Any other ideas?
I just found a proper solution that could work, namely to use the OwnedInstances of AutoFac if I understood correctly. For example:
class MyRepository
{
public MyRepository(Owned<MyDbContext> context, MyDbContext context2)
{
//context and context2 are two different object instances
}
}
This scenario is especially useful if you'd like MyRepository to run in a different transaction, i.e. it needs to have a different DbContext instance than the other repositories.
Once you have different lifetime requirement you must either use another config or manually call container to give you a new instance of the context (or create context instance directly but that is something you don't want to do when using IoC container).

Does Resolve<T>() return objects per-session?

In Microsoft Unity IoC, if I call Resolve<SomeType>(), can I guarantee that the object returned is the one that was created during the current session?
For example, three users sign on, and let's say that the object of SomeType that gets created in the container has different values for each user. Will a call to Resolve return the object that was created for the current user? Or would it do something stupid like return the last one that was created?
I'm having troubles testing this myself due to some environment problems and I need to check something in soon, so if someone could answer this it would be very helpful!
Edit
Forgive me for I am very new to Unity, but based on what I read here, it seems like I should be able to register objects in the container with a unique name and retrieve them by that name. So, wouldn't I be able to use a session ID or some other value that persists within a session to retrieve my object?
Oh wow, lifetime management using Unity in am MVC app. Where do I start?
First of all, session singletons are not really possible as there is no ASP.NET system that will guarantee that the same instance will be used between requests in the same session. The session can mimic the same object persisted within the session by serializing and deserializing it between requests.
Transient instances - i.e. simple registrations without lifetime management specification are sufficient 99% of the time. This implies that an instance of registered type will be created every time it is needed.
It is very rarely that you need instances to live throughout the lifetime of the request. However when you need those, you really need those. A connection to a DB is a perfect candidate for this. Request singletons, on the other hand are much easier to create and manage.
The most elegant solution is to use Unity's child container feature. A child container can be created at the beginning of the request, disposed at the end of the request (as an added bonus it will dispose all ContainerControlledLifetimeManager instances).
When creating a child container, all registrations are still available from the parent container, so you need to register request specific stuff with the child container.
Here is pseudo-code to get this working:
private void Application_Start() {
_parentContainer = new UnityContainer();
//creates a transient registration, available at any point in the app.
_parentContainer.RegisterType<IParentIntf, ParentIntfImpl>();
ControllerBuilder.Current.SetControllerFactory(new ServiceLocatorControllerFactory());
}
private void Application_BeginRequest() {
var childContainer = _parentContainer.CreateChildContainer();
//registers a request "singleton"
//This registration is a type registration, an instance of RequestInterfaceImpl
//will be created when needed and then kept in the container for later use.
childContainer.RegisterType<IRequestInterface,RequestInterfaceImpl>(new ContainerControlledLifetimeManager());
//save the child container in the context, so we can use it later
HttpContext.Items["childContainer"] = childContainer;
}
private void Application_EndRequest() {
//dispose the child container
((IUnityContainer)HttpContext.Items["childContainer"]).Dispose();
}
One other thing that needs to be done is to override the Controller Factory to use the child container to create controllers. Controller are the first point of entry into the application and they could simply take a dependency on other components in their constructor.
public class UnityControllerFactory : DefaultControllerFactory {
#region IControllerFactory Members
public override IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName) {
IController controller;
controllerName = controllerName.ToLower();
var container = ((IUnityContainer)HttpContext.Items["childContainer"])
if(container.IsRegistered<IController>(controllerName))
controller = container.Resolve<IController>(controllerName);
else
controller = base.CreateController(requestContext, controllerName) ;
return controller;
}
}
The default behaviour will be to return a new instance for each resolve call, this isn't what you want.
It would be possible to create and resolve the same instance within a session, but there is no built in support as far as I know. You would have to write your own lifetime manager, and then use this when registering your type.
There is a lifetime manager that can do per thread instances, but this isn't useful for sessions as threads will get re-used, and resolve would need to also work across multiple requests to be truly session-scoped.
It's entirely possible that someone has written a lifetime manager for this.

Categories