Garbage Collection and Visual Studio

  • Thread starter Thread starter Steve Murphy
  • Start date Start date
S

Steve Murphy

I'm working on an application where I use a single connection repeatedly to load
records into a detail area, opening and closing the connection for each use. I
do not use a VS connection control for this, I use my own code.

So when the associated form is closed, where is the best place to finally
dispose of that connection? I'm assuming that in the VS-generated override to
Dispose would be the proper place, but I am hestitant to modify that method,
since it is generated by VS.

Thanks in advance,
Steve Murphy
 
If you "use your own code" I assume that you have a class that manages the
connection? then use the Dispose method of that class.
If you are just creating a connection object using OLEDB Connection classes,
and you repeatedly create a connection object, assign the connection string,
use the object, and close the object, then you don't have to worry about it.

Personally, I like using the Using construct, since it calls Dispose for
you, even if an exception is raised. Pretty nice.

--
--- Nick Malik [Microsoft]
MCSD, CFPS, Certified Scrummaster
http://blogs.msdn.com/nickmalik

Disclaimer: Opinions expressed in this forum are my own, and not
representative of my employer.
I do not answer questions on behalf of my employer. I'm just a
programmer helping programmers.
 
Steve Murphy said:
I'm working on an application where I use a single connection repeatedly to load
records into a detail area, opening and closing the connection for each use. I
do not use a VS connection control for this, I use my own code.

So when the associated form is closed, where is the best place to finally
dispose of that connection? I'm assuming that in the VS-generated override to
Dispose would be the proper place, but I am hestitant to modify that method,
since it is generated by VS.

It sounds to me like you're needlessly hanging onto the connection.
Personally, I'd recommend creating a new SqlConnection (or whatever)
and opening it then disposing it (with a using statement) every time
you need it. Let the connection pool manage the database connection -
that's what it's there for.

That way you need never have a connection associated with the form
itself, so the lifetime issue doesn't come up.
 
If you "use your own code" I assume that you have a class that manages the
connection?

Not yet. I'm new to C# and .NET. This application is more of a proof of concept,
where I've duplicated the look and feel I used on my old platform. I plan to
move all data access code into separate classes in a data layer, but I haven't
gotten there yet. My first step was to satisfy myself that I could do the same
kinds of things with C#.NET that I used to do on my old platform, and with the
same relative ease.

then use the Dispose method of that class.

Yes, but where would I dispose of the class object? Remember, I want to resuse
the same connection object until the form is unloaded. Should I dispose of the
connection in the form's Dispose method? If so, are there any gotcha's from
Visual Studio when I modify that method?

If you are just creating a connection object using OLEDB Connection classes,
and you repeatedly create a connection object, assign the connection string,
use the object, and close the object, then you don't have to worry about it.

I create it once in the form's load event. Then I open and close it, as needed.

Personally, I like using the Using construct, since it calls Dispose for
you, even if an exception is raised. Pretty nice.

Yes, I was just reading about that approach in the "Visual C#.NET 2003
Unleashed" book by Hoffman and Kruger. It is pretty nice. But does that apply
here, since I don't want to dispose of the connection object until the form is
unloaded?


Thank you for the reply,
Steve Murphy
 
Jon Skeet is right... don't do it. Don't create the connection object on
Form Load and then attempt to throw it away later.

Create the object,
assign the connection string
use the object
dispose of it (Using is a great way to do this).

If you have three methods that need to get data, let them all do the same
thing.

Connection pooling (which is MUCH more efficient than anything you can add)
will do the work of tracking connections to SQL Server.

--
--- Nick Malik [Microsoft]
MCSD, CFPS, Certified Scrummaster
http://blogs.msdn.com/nickmalik

Disclaimer: Opinions expressed in this forum are my own, and not
representative of my employer.
I do not answer questions on behalf of my employer. I'm just a
programmer helping programmers.
--
 
It sounds to me like you're needlessly hanging onto the connection.
Personally, I'd recommend creating a new SqlConnection (or whatever)
and opening it then disposing it (with a using statement) every time
you need it. Let the connection pool manage the database connection -
that's what it's there for.

That way you need never have a connection associated with the form
itself, so the lifetime issue doesn't come up.

Hhhmmm, yes. I see the error of my ways. So there is no performance penalty at
all then, if I create a new connection each time?

Thanks,
Steve Murphy
 
It sounds to me like you're needlessly hanging onto the connection.
Personally, I'd recommend creating a new SqlConnection (or whatever)
and opening it then disposing it (with a using statement) every time
you need it. Let the connection pool manage the database connection -
that's what it's there for.

That way you need never have a connection associated with the form
itself, so the lifetime issue doesn't come up.


Okay, one more question though. When you create an adapter, you create the
commands for that off a connection? Don't you need to keep that connection
around for the life of the adapter?

Or are you saying that the adapter should also be created and disposed of, as
needed? And how does that affect binding to controls on the form for datasets
created from the adapter?

Please bear with me if these questions are elementary. As I said, I'm fairly new
to C# and .NET.

Thanks again,
Steve Murphy
 
Steve Murphy said:
Hhhmmm, yes. I see the error of my ways. So there is no performance
penalty at all then, if I create a new connection each time?

Only the tiny (really, really tiny) penalty of creating a new object,
and the lookup of the connection string within the connection pool.
Nothing to even *slightly* concern yourself over.
 
Steve Murphy said:
Okay, one more question though. When you create an adapter, you create the
commands for that off a connection? Don't you need to keep that connection
around for the life of the adapter?

Not necessarily. You can create connections and set the connection in
the command just before calling any of the methods on the adapter.
Dispose of the connection and it won't matter whether or not it's
garbage collected before you next set the Connection property to be a
new connection object. (You could always set the Connection property to
be null afterwards, if you wanted.)
Or are you saying that the adapter should also be created and disposed of, as
needed? And how does that affect binding to controls on the form for datasets
created from the adapter?

I haven't actually done much with binding adapters to controls - the
one project I worked on that really used data bindings only bound to
the data tables involves. Then again, we didn't use the designer for
any of the binding, which may well have made a difference.
Please bear with me if these questions are elementary. As I said, I'm fairly new
to C# and .NET.

No problem.
 
Not necessarily. You can create connections and set the connection in
the command just before calling any of the methods on the adapter.
Dispose of the connection and it won't matter whether or not it's
garbage collected before you next set the Connection property to be a
new connection object. (You could always set the Connection property to
be null afterwards, if you wanted.)

I see. But you wouldn't want to dispose of the adapter and it's commands after
every use, would you? Or would you? I mean, wouldn't that be a lot of code
running repeatedly for every action you performed against the database?

Which then brings back the question: Where is the best place to dispose of those
resources? Would you do it in the form's Dispose method, the code for which is
generated by Visual Studio, or would it be safer to do in the form's Closed
event method?

I haven't actually done much with binding adapters to controls - the
one project I worked on that really used data bindings only bound to
the data tables involves. Then again, we didn't use the designer for
any of the binding, which may well have made a difference.

Actually, I have the controls bound to the dataset/datatable, as well, and I've
done the binding manually, not through the VS designer. So I guess it's not an
issue.


Thanks again,
Steve Murphy
 
Steve Murphy said:
I see. But you wouldn't want to dispose of the adapter and it's commands after
every use, would you? Or would you? I mean, wouldn't that be a lot of code
running repeatedly for every action you performed against the database?

I don't think setting up the adapter actually takes much code - it's
not really doing a lot. (In our code the data adapter was actually well
away from the UI code, in a class which lived for as long as the app
did, so it wasn't an issue.)
Which then brings back the question: Where is the best place to
dispose of those resources? Would you do it in the form's Dispose
method, the code for which is generated by Visual Studio, or would it
be safer to do in the form's Closed event method?

Hmm... not sure. One alternative is to add it to the container called
"components". That way it gets disposed of during Dispose without you
having to add any code.
Actually, I have the controls bound to the dataset/datatable, as
well, and I've done the binding manually, not through the VS
designer. So I guess it's not an issue.

I'm glad I'm not the only one who prefers hand-written code to the
stuff that the designer pumps out :)
 
Jon Skeet said:
I'm glad I'm not the only one who prefers hand-written code to the
stuff that the designer pumps out :)

I assume that if you want control, then you need to bite the bullet and write
the code yourself. I'm not sure how you would go about separating your data
layer if you let the designer generate the code.

Steve Murphy
 
Jon Skeet said:
Hmm... not sure. One alternative is to add it to the container called
"components". That way it gets disposed of during Dispose without you
having to add any code.

How do you do this?

Thanks,
Steve Murphy
 
Steve Murphy said:
How do you do this?

The designer will create a variable called "components" of type
System.ComponentModel.Container. It's initialized in
InitializeComponent, and you can add components to it. I *think*
anything you add to that will automatically get disposed when the form
is disposed - but I can't say I've tried it, I'm afraid.
 
Jon Skeet said:
The designer will create a variable called "components" of type
System.ComponentModel.Container. It's initialized in
InitializeComponent, and you can add components to it. I *think*
anything you add to that will automatically get disposed when the form
is disposed - but I can't say I've tried it, I'm afraid.

The components.Add() call requires a parameter of type
System.ComponentModel.Component. From the associated docs, it appears that this
is intended for COM objects. Or am I reading this all wrong?

In any event, I suppose I could put my Dispose code after the call to
base.Dispose(), or in the form's Close event. Or is there anything wrong with
those approaches?

Thanks again,
Steve Murphy
 
Let me correct myself. The problem was that "componets" was set to null. By
initializing it with a constructor it compiles and runs.

However, when I check my adapter object after the components.Dispose() call, it
is still there. Should this be cleared immediately?

Thanks,
Steve Murphy
 
Steve Murphy said:
Let me correct myself. The problem was that "componets" was set to null. By
initializing it with a constructor it compiles and runs.

You shouldn't need to, so long as you only add things *after* the call
to InitializeComponent. If you do it before the call to
InitializeComponent, the old value will be overwritten by the designer
code.
However, when I check my adapter object after the components.Dispose() call, it
is still there. Should this be cleared immediately?

What do you mean by "it is still there"? Being disposed doesn't stop
there from being a live reference to it - but any unmanaged resources
should have been cleared.

What I'm still not entirely sure about is whether or not
components.Dispose() goes through every component disposing of each of
them.
 
Jon Skeet said:
You shouldn't need to, so long as you only add things *after* the call
to InitializeComponent. If you do it before the call to
InitializeComponent, the old value will be overwritten by the designer
code.

No, "components" is still null after the call to InitializeComponent(). The only
way I can make the call to components.Add() is to initialize "components" to an
instance of System.ComponentModel.Container. The VS-generated code sets it to
null and leaves it there for my app.

However, on closer examination, I see that even though the call to
components.Add() executes, the objects don't actually get added to the
container. The .NET Framework docs seem to indicate that what the Add() method
is looking for is an object of the Component class, and not an adapter, so
therein may lie the problem. Although you would think that an exception would be
generated.

What do you mean by "it is still there"? Being disposed doesn't stop
there from being a live reference to it - but any unmanaged resources
should have been cleared.

It's still there with all of its contents intact. Its resources only get set to
nulls if I dispose of it directly.


Thanks again,
Steve Murphy
 
Steve Murphy said:
No, "components" is still null after the call to InitializeComponent(). The only
way I can make the call to components.Add() is to initialize "components" to an
instance of System.ComponentModel.Container. The VS-generated code sets it to
null and leaves it there for my app.

Very odd. Have you had a look at the code inside InitializeComponent?
In the empty project I've got, it gets created there...
However, on closer examination, I see that even though the call to
components.Add() executes, the objects don't actually get added to the
container. The .NET Framework docs seem to indicate that what the Add() method
is looking for is an object of the Component class, and not an adapter, so
therein may lie the problem. Although you would think that an exception would be
generated.

Well, DataAdapter is a component...
It's still there with all of its contents intact. Its resources only get set to
nulls if I dispose of it directly.

Hmm. Given the various problems, this doesn't sound like it's going to
be particularly productive :( I suggest you just hijack the designer-
generated Dispose method. If you wanted to keep what's there there, you
could create your own class derived from the designer-created class,
and override Dispose there. Always create an instance of the derived
class rather than an instance of the designer-created class.
 
Steve Murphy said:
Not there. I'll create an empty project and check it there. I've been
using this app to try out a number of things. It's possible that I
did something to muck up the designer code.

Possibly - or that an empty project has it, but many others don't :(
Agreed. So you like putting it the designer's dispose method rather
than the form's Close event method?

I think it's generally a good idea to do all the disposing at the same
time. It may well not make the blindest bit of difference really
though.
 
Back
Top