I'm adapting some code originally written for Windsor to use StructureMap. In the Windsor example we release the handler. Is it necessary to do this with StructureMap instances that are cached "per request"? The code is:
foreach (var handler in ObjectFactory.GetAllInstances<IHandle<TEvent>>()) {
handler.Handle(#event);
// do I need to dispose here?
}
// or should I do this:
ObjectFactory.EjectAllInstancesOf<IHandle<TEvent>>();
Thanks
Ben
StructureMap does not hold on to references to "pre request" instances at all, so you do not have to take any steps to tell StructureMap to release them.
However, if retrieved services expect to be explicitly disposed (because they implements IDisposable), it is still your responsibility to dispose them. StructureMap just gives you the instance, and its up to you to use it appropriately.
With one exception - if you retrieve an IDisposable instance from a nested container, Dispose() will be called on the instance when the nested container is disposed.
Related
I've recently started developing with ASP.NET MVC and some examples I've found override the Dispose() method in the base controllers but most do not.
What is the point of Dispose and when should it be overridden and when is it not necessary
In general in .net you need to implement IDisposable if your class are creating any IDisposable objects and storing them as instance variables/properties. There are possible exceptions to this rule. But the point with IDisposable is to clean up system resources the garbage collector can't by itself.
So if your class is creating IDisposables, it also need to make sure they are cleaned up. Either by using(someDisposableChildObject){} directly or through implementing IDisposable and calling someDisposableChildObject.Dispose() in the Dispose method.
ASP.NET Core uses extension methods on IServiceCollection to set up dependency injection, then when a type is needed it uses the appropriate method to create a new instance:
AddTransient<T> - adds a type that is created again each time it's requested.
AddScoped<T> - adds a type that is kept for the scope of the request.
AddSingleton<T> - adds a type when it's first requested and keeps hold of it.
I have types that implement IDisposable and that will cause problems if they aren't disposed - in each of those patterns when is Dispose actually called?
Is there anything I need to add (such as exception handling) to ensure that the instance is always disposed?
The resolved objects have the same life-time/dispose cycle as their container, that's unless you manually dispose the transient services in code using using statement or .Dispose() method.
In ASP.NET Core you get a scoped container that's instantiated per request and gets disposed at the end of the request. At this time, scoped and transient dependencies that were created by this container will get disposed too (that's if they implement IDisposable interface), which you can also see on the source code here.
public void Dispose()
{
lock (ResolvedServices)
{
if (_disposeCalled)
{
return;
}
_disposeCalled = true;
if (_transientDisposables != null)
{
foreach (var disposable in _transientDisposables)
{
disposable.Dispose();
}
_transientDisposables.Clear();
}
// PERF: We've enumerating the dictionary so that we don't allocate to enumerate.
// .Values allocates a ValueCollection on the heap, enumerating the dictionary allocates
// a struct enumerator
foreach (var entry in ResolvedServices)
{
(entry.Value as IDisposable)?.Dispose();
}
ResolvedServices.Clear();
}
}
Singletons get disposed when the parent container gets disposed, usually means when the application shuts down.
TL;DR: As long as you don't instantiate scoped/transient services during application startup (using app.ApplicationServices.GetService<T>()) and your services correctly implement Disposable interface (like pointed in MSDN) there is nothing you need to take care of.
The parent container is unavailable outside of Configure(IApplicationBuilder app) method unless you do some funky things to make it accessible outside (which you shouldn't anyways).
Of course, its encouraged to free up transient services as soon as possible, especially if they consume much resources.
I'm using Entity Framework in my project, and I have the problem that, once I pass my entities to a View (keep in mind that these entities have lazy-initialized objects along the lines of: Products.Owner, where owner is an object that is lazily initialized) I get a run-time exception telling me that the ObjectContext is out of scope.
Now this makes sense since I am getting the entities from a Service with a using (.... entities...) { .... } statement, which means it is disposed when the result is returned.
How would I get around this and have an Object Context that is alive from start to end. Thanks.
One option is to associate the repository with the Request, and have the Repository implement IDisposable, and have the Dispose method dispose of the contained ObjectContext, rather than using the more familiar using pattern inside your controller actions.
I have an ASP.NET MVC app that creates a Linq2SQL datacontext on a per-web-request basis using Castler Windsor IoC.
For some reason that I do not fully understand, every time a new datacontext is created (on every web request) about 8k of memory is taken up and not released - which inevitably causes an OutOfMemory exception.
If I force garbage collection the memory is released OK.
My datacontext class is very simple:
public class DataContextAccessor : IDataContextAccessor
{
private readonly DataContext dataContext;
public DataContextAccessor(string connectionString)
{
dataContext = new DataContext(connectionString);
}
public DataContext DataContext { get { return dataContext; } }
}
The Windsor IoC webconfig to instantiate this looks like so:
<component id="DataContextAccessor"
service="DomainModel.Repositories.IDataContextAccessor, DomainModel"
type="DomainModel.Repositories.DataContextAccessor, DomainModel"
lifestyle="PerWebRequest">
<parameters>
<connectionString>
...
</connectionString>
</parameters>
</component>
Does anyone know what the problem is, and how to fix it?
L2S DataContext implements IDisposable. Your interface also has to implement it, and call DataContext.Dispose(), so that Windsor knows that there're resources to be disposed.
By the way beware of Windsor/IDisposable problems:
http://www.jeremyskinner.co.uk/2008/05/03/aspnet-mvc-controllers-windsor-and-idisposable/
http://www.nablasoft.com/Alkampfer/?p=105
No your DataContextAccessor does not need to implement IDisposable. Windsor is smart enough to handle the case without having to do any modifications to your classes.
However since as noted in the other answers DataContext does implement it, and Windsor sees it and it registers it for cleanup (to call the Dispose method on it).
What you need to do is to call container.Release and pass your root service (which probably would be DataContextAccessor in your case). Windsor will then release it and all its dependencies (it will also call Dispose on DataContext) and the memory will be freed.
If you're using ASP.NET MVC consider using MVCContrib project which has Windsor integration that handles releasing of components for you.
From what I can tell, queen3 is correct, your DataContextAccessor class needs to implement IDisposable and call datacontext.Dispose() from its .Dispose() method. (Disclaimer: I haven't worked with Castle Windsor.)
Alternatively, what I would do is turn your DataContextAccessor into a DataContextFactory, which only creates the DataContext when you call a method (e.g. GetContext()). Then you can do this:
using(DataContext context = myDataContextFactory.GetContext()) {
// Do whatever you want with the context
}
// Context is disposed here
You might also want to take a look at this previous question: How do you reconcile IDisposable and IoC?
I think #Krzysztof Koźmic is right... you should release whatever you get from Windsor.
Windsor is pretty alien to anyone used to IDisposable. The reason for this apparent disparity is down to the management of the component's lifecycle. If you take a component from Windsor that is IDisposable, you don't know if that instance is configured as transient or a singleton (and of course this could change as your app evolves).
If you dispose a component and it later turns out to be a singleton, some other client code is going to be wondering why its component has suddenly failed!?! Only Windsor is able to make the Disposal decision for you.
Nice blog post Krzysztof (won't let me post link!)
In our app we've made everything transient, apart from a couple of singletons. Transient seems to be the simplest model (as long as everyone understands you must 'Release rather than Dispose'). If you have a mock container in your tests, you can set an expectation that Release is called for each component your mock resolves, and I've also heard that transient has fewer performance issues (??) than other modes? The code is certainly more portable.
Last but not least, if you have a memory leak and you need to work what and why something isn't being collected by the GC, check out Tess Ferrandez' fab tutorial series on windbg
http://blogs.msdn.com/b/tess/archive/2008/04/03/net-debugging-demos-lab-7-memory-leak-review.aspx ... the culprit may be somewhere unexpected!
I have using blocks in each method of my repository. If I want to cross reference methods, it seems it would be against best practices to initialize another Datacontext What am i doing wrong? If I declare a Datacontext in the class instead of using blocks in methods will I not lose power to dispose ??
public IList<something> GetSomething()
{
using (DB db=new DB())
{ ...GetListofSomethingElse(id)
}
}
public IList<somethingelse> GetListofSomethingElse(int id)
{
using (DB db=new DB())
{
... return IList
}
}
Actually, I think it is semantically (or how should I say that), not correct to create and dispose a datacontext in your repository.
I mean: if you open a new connection to the DB in each and every method of your repository, you're doing it wrong IMHO. This is too much fine grained.
The repository class has no knowledge of the 'context' in which it is being used. Your repository should not be responsible for opening / closing connections or starting and committing transactions.
Context is king, and the repository has no knowledge of the context in where it is being used. So, IMHO it is the responsability of the Application layer or service layer to open new DataContext objects, and closing / disposing them. (The same applies for transactions).
So, this is how I do it: (note that I do not use the Entity Framework, but I use NHibernate. I assume that the DataContext class in the EF is similar to the ISession in NHibernate):
using( ISession s = theSessionFactory.OpenSession() )
{
ICustomerRepository cr = RepositoryFactory.GetCustomerRepository(s);
Customer c1 = cr.GetCustomer(1);
Customer c2 = cr.GetCustomer(2);
// do some other stuff
s.StartTransaction();
cr.Save (c1);
cr.Save (c2);
s.Commit();
}
(This is not real world code offcourse; and it won't even compile since ISession doesn't have a Commit method. ;) Instead, the StartTransaction returns an ITransaction which has some kind of commit method, but I think you'll catch my drift. ;) )
If you don't use a using statement, you can still dispose explicitly. Even if you don't dispose of the data context though, cross-referencing these methods will still create a new data context. That may or may not be a good thing, depending on your usage. Think about the state management aspect of the data context, and whether you want to isolate the methods from each other or not. If you want to avoid creating a new context all the time, overload the methods with versions which take the context as a parameter.
Note that you don't usually need to dispose of a data context, although I tend to dispose of anything implementing IDisposable.
The using statement is syntactic sugar. It compiles to a try/finally block with the Dispose() call in the finally section. It ensures that Dispose will be called even if an exception occurs.
You can call .Dispose() on a class without using a 'using' statement - usually you'll do this in the Dispose method of your repository, if you've got one.