Just a quick sanity check here!
If I have a static method in an instance class e.g:
public class myClass
{
public static void AMethod()
{
//do somit
}
}
Would it cause problems if I was making reference to IDisposable resources in the method body, an object context for example?
public static void AMethod()
{
ObjectContext context = new ObjectContext();
// do somit
}
By would it cause problems, I mean, would it retain the object context behind the scenes after the end of the method body due to the fact it was a static method?
The class as can be seen, isn't static, and the variable is local to the method.
I'm aware that I should be using 'using' here, just curious as to whether this particular combo of events could/would cause memory leaks.
In order to avoid any problems it is recommended to dispose IDisposable resources as soon as you have finished using them. This could happen by wrapping them in a using statement:
public static void AMethod()
{
using (ObjectContext context = new ObjectContext())
{
// do something
}
}
After leaving the scope of your method AMethod, your context object can't be used anymore so it'll be garbage collected eventually.
But as it implements IDisposable, you should use the using statement:
using (ObjectContext context = new ...)
{
// Use the context here
}
Related
In all the examples I see for Entity Framework data access, every method has its own using block, as shown below.
Is there an alternative to this approach? For example, can the context object just be a class member, such as:
MyModelContext context = new MyModelContext();
Is there a reason why a new context object has to be created for each method in the DAO class?
public class DaoClass
{
public void DoSomething()
{
using (var context = new MyModelContext())
{
// Perform data access using the context
}
}
public void DoAnotherThing()
{
using (var context = new MyModelContext())
{
// Perform data access using the context
}
}
public void DoSomethingElse()
{
using (var context = new MyModelContext())
{
// Perform data access using the context
}
}
}
You could have the DaoClass implement IDisposable and have the context be a property of the class. Just make sure to wrap DaoClass in a using statement or call Dispose() on the instance of the DaoClass.
public class DaoClass : IDisposable
{
MyModelContext context = new MyModelContext();
public void DoSomething()
{
// use the context here
}
public void DoAnotherThing()
{
// use the context here
}
public void DoSomethingElse()
{
// use the context here
}
public void Dispose()
{
context.Dispose();
}
}
Please note that the context object is the equivalent to a database transaction.
It implements the IDisposable interface because a transaction must be closed when done with and you either have to use the using statement or make an implementation of IDisposable like Lews Therin demonstrated.
We use multiple instances of a context object to separate different transactions. There will be cases when you want all changes to go as a single transaction and either commit all together or rollback everything. Then you put it all in one context instance. But there will also be cases where you want to separate the saving of one data pack from another. Then you use different transactions, i.e. different context objects.
To get a better grasp of this chapter take a look at the unit of work pattern.
Hope I could help, merry coding!
The way you show it is how I've seen it recommended everywhere. I've seen there be weird issues with class level declaration returning stale or incorrect data.
To get around duplicating all the code I like to write an execute method that I can reuse, or make changes without having to go to every using.
private T Execute<T>(Func<MyModelContext, T> function)
{
using (MyModelContext ctx = new MyModelContext())
{
var result = function(ctx);
ctx.SaveChanges();
return result;
}
}
public List<Type> GetTypes()
{
return Execute((ctx) =>
{
return ctx.Types.ToList();
});
}
Can we use the using statement in a constructor to declare an instance of an object for later usage. For example.
public class TestClass {
private DataClassesDataContext _dataContext;
public TestClass(string connString){
using (this._dataContext = DataClassesDataContext(connString));
}
private bool someMethod(){
_dataContext.instanceMethod(); // i want to use instance methods wherever needed and define once
}
}
You must implement IDisposable yourself and call Dispose on the data context from you Dispose method.
public class TestClass : IDisposable {
private DataClassesDataContext _dataContext;
public TestClass(string connString){
_dataContext = new DataClassesDataContext(connString);
}
private bool someMethod(){
_dataContext.instanceMethod(); // i want to use instance methods wherever needed and define once
}
public void Dispose(){
_dataContext.Dispose();
}
}
It's not clear what you expect the using statement to do here. All it does is make sure that Dispose is called at the end of the block.
So basically you'd be creating a DataClassesDataContext (I assume you missed the new keyword...), storing a reference in a field, and then immediately disposing of it. That's not going to work well - you should get rid of the using statement, but quite possibly make your class implement IDisposable so that when the instance of TestClass is disposed, you dispose of the data context.
According to MSDN:
The using statement calls the Dispose method on the object in the
correct way, and (when you use it as shown earlier) it also causes the
object itself to go out of scope as soon as Dispose is called.
The using statement is basically syntactic sugar for try/finally.
try
{
_dataContext = new DataClassesDataContext(connString);
}
finally
{
if (_dataContext != null)
((IDisposable)dataContext).Dispose();
}
Looking at it in this way it should become obvious that datacontext is no longer in scope and therefore can't be used by other methods as you desire. To solve the problem, you should make the class implement IDisposeable.
using (this._dataContext = DataClassesDataContext(connString));
is the same as
try
{
this._dataContext = DataClassesDataContext(connString);
}
catch
{
}
finally
{
if(this._dataContext!=null)
((IDisposable)this._dataContext).Dispose();
}
So you'll get _dataContext disposed in you constructor and it will be no longer available. You should implement IDisposable interface and you'll be able to employ using statement where you want like this:
using (TestClass test = new TestClass("conn"))
{
//your code
}
If a class has an instance field that implements IDisposable then the containing class implements IDisposable and class that fields Dispose method from within its Dispose method.
public class A : IDisposable
{
public System.Drawing.Font font = new Font("Arial", 10.0f);
public void Dispose()
{
font.Dispose()
}
}
(I know I didn't do the dispose pattern correctly, but for sample code should be good enough)
If the field is a static field though where should the call to the field's Dispose be?
public class B
{
public static System.Drawing.Font font = new Font("Arial", 10.0f);
}
I could make class B implement IDisposable and have that call font.Dispose but if B.font is used again later on that would cause problems. As well as you'd have to remember that dispise accessing a static method you need to create an instance just to call Dispose.
I could also make a static Dispose method but then users have to remember to call Dispose and have to make sure they're the last user of it in the program.
Static fields are initialised when the type is loaded.
Therefore it logically it makes sense to dispose the object assigned to the static field when the containing type is unloaded.
However, types are not unloaded. There may be some exotic complication here around AppDomains, but I suspect that doesn't apply in your case.
Therefore I wouldn't dispose the instance, otherwise you will have a publicly available instance of an object that is unfit for use.
If the field is static, then maybe the intention is to have it last for the complete duration of the application? Because then it will only need to be disposed of when the application shuts down. And that will happen one way or the other, by itself-
If you plan to reassign the static field to different IDisposable objects several times during the lifetime of the application, then of course you would want to dispose the old object when you reassign. Maybe you could use a property for that? Not that I have thought a lot about it, but something like:
// private - don't write to this field from outside the property setter
static Font font = new Font("Arial", 10.0f));
public static Font Font
{
get
{
return font;
}
set
{
var oldFont = font;
if (oldFont != null)
oldFont.Dispose();
font = value;
}
}
You dispose of it like any other object. It doesn't make a difference. A static object is just an object that is available per class. It's still an instance of something. Granted, you probably wouldn't want to do this since after you dispose of it someone can still access it and get a ObjectDisposedException exception.
static void Main(string[] args)
{
using (Test.Instance)
{
}
Thread.Sleep(TimeSpan.FromSeconds(10));
}
public class Test:IDisposable
{
public static Test Instance = new Test();
public void Dispose()
{
Console.WriteLine("Disposed");
}
}
And the output is:
Disposed
Per your updated example:
public class A
{
public static System.Drawing.Font font = new Font("Arial", 10.0f));
}
You can just do A.font.Dispose() or using(A.font)
In general I think the idea is you really wouldn't have a public static disposable field since by making it static you imply it should be around for the lifetime of the application. If it has to be disposable you should could make it lazy and make it be thread-safely re-initializable, otherwise accessing it after disposing will throw exceptions. Or you can have a hook into your application end code and safely dispose of all static disposables there. You can register your disposable on start somewhere as well. Just an idea
You can't dispose a static class because there is no instance of it
Consider situation when we have a class with couple of static methods that use one static object.
public class Person
{
private static PresonActions actions = new PresonActions();
public static void Walk()
{
actions.Walk();
}
}
I know that the life cycle of static members in asp.net apps is equals to appdomain life cycle.
So this means that the object is not destroyed and the resources are not deallocated until I'll restart the appdomain.
But if we will use a property to create an instance of class PresonActions each time something access it, will the object will be destroyed or not?
public class Person
{
private static PresonActions actions { get { return new PresonActions(); } }
public static void Walk()
{
actions.Walk();
}
}
thanks.
Static variable continuouse allocation is an Evil. Keep an eye on your memory consuption, especially if you are talking about server side component (ASP.NET).
To answer your question: GC collects when he can an object which none longer reference by anyone in application.
Do not do this. It's very easy jump into memory problems with this approach and after spend hours to profile and find memory leaks.
If you want to change an object content, write a function that updates object content, without creating a new instance of it.
In your second code example, the garbage collector will destroy the object some time after the call to actions.Walk(). The garbage collector does this in a non-deterministic fashion, i.e. you cannot determine when it will perform this operation.
If your type is using resources which you want to dispose of deterministically, then the type should implement IDisposable and it's implementation of the Dispose method should perform the disposal of those resources.
Consuming code can then either call this method directly or use a using block to dispose of the object which in turn disposes of it's resources.
e.g.:-
public class PresonActions : IDisposable
{
...
public void Dispose()
{
...
}
}
public class Person
{
public static void Walk()
{
using(var actions = new PresonActions())
{
actions.Walk();
}
}
}
Note that, since you are not using the instance for more than one method call, there is no point creating it in a static property. It can be created it within the method, which allows use of a using block.
I have the following code:
A disposable class that contains two disposable members.
One of them is being initialized using new() method, and the other using static factory method.
I Also have static code analisys rules, with CA2213 as error.
public class DisposableClass : IDisposable
{
private WebClient m_DisposableMember1;
public WebClient DisposableMember1
{
get
{
if (m_DisposableMember1 == null)
{
m_DisposableMember1 = new WebClient();
}
return m_DisposableMember1;
}
}
private WebClient m_DisposableMember2;
public WebClient DisposableMember2
{
get
{
if (m_DisposableMember2 == null)
{
m_DisposableMember2 = Factory.Create();
}
return m_DisposableMember2;
}
}
#region Finalize/Dispose Pattern
private bool m_IsDisposed = false;
//Implement IDisposable.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~DisposableClass()
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
if (!m_IsDisposed)
{
if (disposing)
{
DisposableMember1.Dispose();
// DisposableMember2 in not disposed and not notified by fxCop
}
m_IsDisposed = true;
}
}
#endregion Finalize/Dispose Pattern
}
This is the simple factory class:
public static class Factory
{
public static WebClient Create()
{
return new WebClient();
}
}
When I call the Dispose() method of the DisposableMember1 property, I get CA2213.
When I call the Dispose() method of the m_DisposableMember1 member, I don't get this error.
More over, I don't get this error for m_DisposableMember2 (Wich was initialized using the static factory), and it is not being disposed.
Does anybody familiar with this issue? What can cause this behavior?
CA2213 is not particularly aggressive about identifying fields that ought to be disposed. Amongst other potential problems, it only considers fields that are directly assigned from a constructor invocation. Assignment of a field value via a property or from a source other than a constructor invocation do not result in the target field being included in the pool of "should be disposed" fields by the rule.
You are expecting a bit too much out of the smarts of this tool. That the property is an alias for the field is only obvious to human eyes. It requires pretty sophisticated analysis to let a tool see that. FxCop just doesn't have that kind of horse power. Your code is in fact questionable. If the property was never used by the client code then you'll create the WebClient object and immediately dispose it. Use the field instead, test for null and Dispose().
The problem with the second field is probably induced by the need for the tool to avoid unnecessary warnings. It will only complain if it can determine with absolute certainty that the field is ever initialized. Same kind of lack of smarts here, it can't tell that the factory always returns a non-null reference. Only when it sees the constructor being used in the class itself can it be sure that the field needs to be disposed.
It's a good tool, not perfect.