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.
Related
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 am new to dependency injection and have been doing some reading about it, both on StackOverflow and elsewhere. In practice I am having trouble with using it correctly.
To explain the problem, here's a basic situation where I am not sure how to use DI:
Suppose I have some object that is going to be used in several different classes. However, in order for this object to be usable, it needs certain parameters that I don't have at start-up.
A conceivable way that I can see to do this using DI is to create a blank instance of this object, a method to initialize it with the necessary parameters, and a flag for whether or not it is initialized.
To me, this feels like a hack, because the object shouldn't really exist yet and I am just passing a container around, waiting for the responsible code to initialize it. Is this how it is meant to be done, or am I missing the point?
That is indeed a pretty tough thing to get one's head around when getting started with DI, and something that also isn't easily explained.
Your notion that creating a "blank" object that will be initialized later via a method might be a suboptimal solution is correct - an object should be able to do its work at any time; Initialize() methods are what Mark Seemann calls "temporal coupling" in his book Dependency Injection in .NET. This is an anti-pattern that makes the code using the object dependent on the inner workings of that object and thus breaks encapsulation.
The question is when the required information becomes available, what the "responsible code to initialize it" is, and where it gets the information from - and also how it gets access to the object to initialize it. Ideally, this initializing code would itself be injected into your object, and whenever your object's methods/properties are accessed, it requests initialization from that other dependency.
Also, what happens if the IsInitialized flag returns false? Is that still a valid program state?
In general, as an object in a dependency injected object graph, I should either know all my "configuration" data on creation, or know someone who can give it to me (that someone is another object injected as a dependency).
It might help if you could provide a bit more detail about what kind of parameters the object needs and where they need to come from.
Edit
What you're describing in your comment is pretty much exactly my first encounter with this kind of issue; there's a question somewhere here on SO that I posted back then.
The important thing is to build individual classes (usually, there may be exceptions, but what those are is a matter of experience) in such a way that you assume everything the class needs is present. When the program is running, there need to be other classes then that make sure that assumption will not fail.
Setter injection is something I generally try not to have to avoid said temporal coupling; according to Mark Seemann, setter injection should usually only be used when you already have a good default in place that you just overwrite through the setter. In this case, though, the object would not be able to function properly without that dependency.
This may not be the most elegant way to do this (I usually have the luxury to apply DI in pretty closed code-only environments without having to worry about a UI), but it would work (kind of - it compiles, but is still pseudo code):
public class MainForm
{
private readonly IDataManager _dataManager;
private readonly IConnectionProvider _connectionProvider;
private readonly IConnectionReceiver _connectionReceiver;
public MainForm(IDataManager dataManager, IConnectionProvider connectionProvider, IConnectionReceiver connectionReceiver)
{
this._dataManager = dataManager;
this._connectionProvider = connectionProvider;
this._connectionReceiver = connectionReceiver;
}
public void btnConnect_Click()
{
IConnection connection = this._connectionProvider.GetConnection();
if (null != connection)
{
this._connectionReceiver.SetConnection(connection);
this.SetFormControlsEnabled(true);
}
}
private void SetFormControlsEnabled(bool doEnable)
{
}
}
public interface IConnectionProvider
{
IConnection GetConnection();
}
public interface IConnectionReceiver
{
void SetConnection(IConnection connection);
}
public interface IConnection
{
IConnectionWebService ConnectionWebService { get; }
}
public class ConnectionBridge : IConnection, IConnectionReceiver
{
private IConnection _connection;
#region IConnectionReceiver Members
public void SetConnection(IConnection connection)
{
this._connection = connection;
}
#endregion IConnectionReceiver Members
#region IConnection Members
public IConnectionWebService ConnectionWebService
{
get { return this._connection.ConnectionWebService; }
}
#endregion
}
public interface IConnectionWebService {}
public interface IDataManager { }
public class DataManager : IDataManager
{
public DataManager(IConnection connection)
{
}
}
So, MainForm is the thing that holds it all together. It starts out with its controls disabled, because it knows they need a working IDataManager and that will (by convention) need a connection. When a "connect" button is clicked, the form asks its IConnectionProvider dependency for a connection. It does not care where that connection comes from; the connection provider might display another form to ask for credentials or maybe just read them from a file.
Then the form knows that the connection has to be passed on to the IConnectionReceiver instance, and after that all controls can be enabled. This is not by any DI principle, this is just how we have defined that MainForm works.
The data manager on the other hand has everything it needs from the start - an IConnection instance. That can't do what it's supposed to do at first, but there is other code preventing that from causing problems.
ConnectionBridge is both a decorator for the actual IConnection instance and an adapter decoupling connection acquisition from connection consumption. It does that by employing the Interface Segregation Principle.
As a note on the side, be aware that while Dependency Injection is an important technique, it is only one of several principles you should follow to write what is known as "clean code". The most well known are the SOLID principles (of which DI is one), but there are others like Command-Query-Separation (CQS), "Don't repeat yourself" (DRY) and the Law of Demeter. On top of all that, practice unit testing, precisely Test Driven Development (TDD). These things really make a tremendous difference - but if you're taking up DI of your own accord, you're already off to a good start.
I agree with what GCATNM said and i would like to add that whenever i feel there is an object like this i go and use one of the Factory pattern variants (be it an Abstract Factory, Static Factory, etc ..) and i would inject the factory with the source of the configuration information for this object. So as Marc Seemann also said and i am not quoting: Factories are a great companion of Dependency Injection and you will need them occasionally.
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.
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!