How to clear controls from a form - Help Needed

  • Thread starter Thread starter Siv
  • Start date Start date
Cor,
This conversation you are having with Jack raises a question about disposal
which I have never been fully happy about. I often create functions that
return say a datareader to the caller. The purpose being to have a nice
little black box that does the job of getting data from a database based on
the paramters you send it.

My function would look something like this:

Private Function GetData(ByVal ID as integer) as SQLDatareader
Dim DR as SQLDataReader=nothing
Dim Cmd as SQLCommand=Nothing
Dim Cn as SQLConnection= Nothing
Dim strSQL as string = ""

Try

strSQl = "Select * From SomeTable where fkSomeForeignKey=" &
ID.Tostring & " ORDER BY SomeField;"
Cn = New SqlConnection(ConnString)
Cn.Open()

Cmd = New SqlCommand(strSQL, Cn)
Dr = Cmd.ExecuteReader(CommandBehavior.CloseConnection)

Return Dr

Catch ex As Exception

PEH("GetAllRecords", "Documents Class", ex.Message)
Return Dr

End Try
End Function

What I would really like to do is have a Finally block that disposes od Dr,
but if I do that I will get an error when I try and read the returned
DataReade in the calling routine as the Finally call will remove the version
I have sent to the caller before it gets it.

Is just leaving the function like that OK, or is there some way you can send
a copy of the datareader back to the caller and dispose the one in the body
of the function without causing problems?


Siv
 
Siv,

You could load a datatable from the datareader and return the datatable. But
you can't return a copy of the datareader.

Kerry Moorman
 
Cor,
This conversation you are having with Jack raises a question about disposal
which I have never been fully happy about. I often create functions that
return say a datareader to the caller. The purpose being to have a nice
little black box that does the job of getting data from a database based on
the paramters you send it.

My function would look something like this:

Private Function GetData(ByVal ID as integer) as SQLDatareader
Dim DR as SQLDataReader=nothing
Dim Cmd as SQLCommand=Nothing
Dim Cn as SQLConnection= Nothing
Dim strSQL as string = ""

Try

strSQl = "Select * From SomeTable where fkSomeForeignKey=" &
ID.Tostring & " ORDER BY SomeField;"
Cn = New SqlConnection(ConnString)
Cn.Open()

Cmd = New SqlCommand(strSQL, Cn)
Dr = Cmd.ExecuteReader(CommandBehavior.CloseConnection)

Return Dr

Catch ex As Exception

PEH("GetAllRecords", "Documents Class", ex.Message)
Return Dr

End Try
End Function

What I would really like to do is have a Finally block that disposes od Dr,
but if I do that I will get an error when I try and read the returned
DataReade in the calling routine as the Finally call will remove the version
I have sent to the caller before it gets it.

Is just leaving the function like that OK, or is there some way you can send
a copy of the datareader back to the caller and dispose the one in the body
of the function without causing problems?


Siv

The only way I can see to avoid making the caller take responsibility
for disposing of the object is to pass into the GetData method a
delegate that GetData will call passing the DataReader, with the
understanding that when the delegate returns the DataReader will be
disposed. No doubt you would also have to pass some kind of object
through to the delegate, otherwise the delegate would have to have
access to class-level variables to do its work, all of which I think
would get pretty messy.
 
Siv,

Why would you cleanup a datareader itself, which is created in a method. It
will be done as soon as the stack from the program goes out of scope
(removed).

However, don't forget before that to call the method close or dispose (does
practical the same in this situation) to release things as the connection
in the connectionpool etc. in the code you have created.

(Or simple use it in a "using" construction where the dispose from the
datareader is automaticly done and therefore does the same.)

Have a look at this page, there is more information direct accoording to
your finalize question in it.

http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.close.aspx


Cor
 
Kerry,
At the moment I do return the datareader, but I have to leave the Datareader
un disposed in the routine that populated it. As Cor mentioned below it will
get eventually cleaned up when any reference to it is removed.

I just find it strange creating an object and not disposing it?

Siv
 
Jaxk,
Sounds complicated. I assume that just not disposing the datareader means
it will be disposed by the GAC whenever there is nothing referencing it some
time down the line. I just have a problem with not being able to tidy things
up there and then. I don't like loose ends.

Siv
 
Cor,
That really was the answer to my question. That is, I don't need to
implicitly dispose of the Datareader (doing so would stop the function doing
its job anyway) if I can be sure that ultimately the Datareader will be
destroyed when it is no longer referenced I am fine with that. I just don't
want my apps slowly consuming more and more resources as they run and this
was my worry with leaving objects un disposed.

Siv
 
Jaxk,
Sounds complicated. I assume that just not disposing the datareader means
it will be disposed by the GAC whenever there is nothing referencing it some
time down the line. I just have a problem with not being able to tidy things
up there and then. I don't like loose ends.

Siv

The caller should dispose of it. Once your method returns a reference
to the DataReader, ownership of the DataReader should pass to the
caller and the caller becomes responsible for disposing of it.

This isn't any different from your program allocating a GDI object.
Once the object is returned to your program, it becomes your program's
responsibility to dispose it once it is no longer needed.

Whenever you use an object that needs to be disposed, you need to
maintain the concept of ownership - something must be in charge of
knowing when the object is no longer needed and disposing of it.
 
Cor,
That really was the answer to my question. That is, I don't need to
implicitly dispose of the Datareader (doing so would stop the function doing
its job anyway) if I can be sure that ultimately the Datareader will be
destroyed when it is no longer referenced I am fine with that. I just don't
want my apps slowly consuming more and more resources as they run and this
was my worry with leaving objects un disposed.

Siv

This is where Cor and a number of others here disagree. I believe
Cor's opinion is that since the DataReader doesn't do anything useful
in its Dispose method, that there is no reason to call it.

My belief is that if there is a Dispose method it should be called.
First, I don't want to take the time to investigate every object with
a Dispose method to see if that method really does anything. Second,
I don't want to have to remember to make that same investigation for
every new version of the .NET libraries in case at some time in the
future an object starts doing something useful in its Dispose.
 
Jack (and siv),

You did not read my message, in the case of the datareader I wrote that the
close should be called, which does explititly the same as the dispose, that
instead of that using" could be used or because it exlicitly the same as the
close the dispose could be called instead of the close. Those methods in
the datareader dispose releases the connection. However it would not be
needed for the datareader itself as it had no unmanaged resources.
I don't want to have to remember to make that same investigation for
every new version of the .NET libraries in case at some time in the
future an object starts doing something useful in its Dispose.

As it is about this one, you can not even rely on the working of the + and
the -. This is something Microsoft development team careful tries to control
that it does not happen. The DBDataReader.Dispose will stay the same as now
(or somebody should make a very big mistake as every developer can do). That
does not mean that the WhatEverNew.dispose can have extras we don't know
yet, but that can even be something as create a new object or to close your
program.

Don't forget that Microsoft changed in the beginning of Microsoft the name
Mail Server in Exchange, while that was already the name of the mailclient
(curently Outlook). Therefore the change that what you write will happen
agains is low.

Cor
 
Siv,

A lot of people including you use "Dispose" in the context of "Deconstruct".

It is not the same.

The deconstruction (finalizing) is done by the GC, that is the main reason
why it is called managed code.

Cor
 
Jack,
I am pleased to report that in pretty much ebery instance the calling
routine will have something like this:

Dim CallersDR as sqlDataReader=nothing

try
CallersDR = GetData(SomeID)

...
various code that uses the CallersDR.
...

Catch ex as exception
Error handler code
Finally
if not isnothing(CallersDR) then
CallersDR.Close()
End If
End Try

So if I read teh conversations correctly, the line:

CallersDR.Close()

Will not only close the CallersDR but will also close the Dr that is in the
black box routine (GetData(ID)) as well? This is the concept that I didn't
follow and what was worrying me because in my mind I see the Dr used in the
GetData as being a separate object to the one in the above calling routine.
So therefore I have been worrying that this was being left undisposed.

Am I right in surmising from what has been said above that the Dr in GetData
and teh CallersDR in my calling routine are both referencing the same
DataReader object from the moment that the GetData routine returns the Dr it
has to the caller??

If this is correct I will be a happy man as this has clarified something I
have not understood properly.

Siv
 
Jack,
I am pleased to report that in pretty much ebery instance the calling
routine will have something like this:

Dim CallersDR as sqlDataReader=nothing

try
CallersDR = GetData(SomeID)

...
various code that uses the CallersDR.
...

Catch ex as exception
Error handler code
Finally
if not isnothing(CallersDR) then
CallersDR.Close()
End If
End Try

So if I read teh conversations correctly, the line:

CallersDR.Close()

Will not only close the CallersDR but will also close the Dr that is in the
black box routine (GetData(ID)) as well? This is the concept that I didn't
follow and what was worrying me because in my mind I see the Dr used in the
GetData as being a separate object to the one in the above calling routine.
So therefore I have been worrying that this was being left undisposed.

Am I right in surmising from what has been said above that the Dr in GetData
and teh CallersDR in my calling routine are both referencing the same
DataReader object from the moment that the GetData routine returns the Dr it
has to the caller??

If this is correct I will be a happy man as this has clarified something I
have not understood properly.

Siv

There is no "Dr that is in the black box routine (GetData(ID)) as
well". There is only one SqlDataReader. The black box method creates
it and returns a reference to it. The reference that the black box
method holds to the object goes away once the method exits, leaving
only the caller's reference.

It's like this:

Dim dr As New SqlDataReader
Dim dr1 As SqlDataReader = dr
Dim dr2 As SqlDataReader = dr

There is only one object with three references to that object: dr, dr1
and dr2.
 
Jack,

This is where my VB6 roots probably show. I always treat = (equals) as
meaning copy from the right side to the left side. From what you have just
said that isn't the case, in this instance I am making my variable on the
left side actually equal to rather than assigning.

Now I understand that, I can see that if I dispose (or destruct if you
believe what Cor says), the variable on the left side of the argument, I am
also disposing the original one as they are one and the same object.

That actually makes me a lot happier. Also knowing that as soon as I exit
the black box function that reference is removed helps. I feel a lot tidier
knowing that.

Thanks for you help.

Siv
 
Jack,

This is where my VB6 roots probably show. I always treat = (equals) as
meaning copy from the right side to the left side. From what you have just
said that isn't the case, in this instance I am making my variable on the
left side actually equal to rather than assigning.

Now I understand that, I can see that if I dispose (or destruct if you
believe what Cor says), the variable on the left side of the argument, I am
also disposing the original one as they are one and the same object.

That actually makes me a lot happier. Also knowing that as soon as I exit
the black box function that reference is removed helps. I feel a lot tidier
knowing that.

Thanks for you help.

Siv

= does mean copy from the right side to the left. The problem is
determining what is being copied.

..NET has two types of objects, Value and Reference.

Value objects (Integer, DateTime, etc.) are copied.

With Reference objects, references (like pointers in C) are used - the
= operator sets the variable on the left side to be a reference to the
same object as the item on the right. When x and y are references and
you say "x = y" you are copying the value of y to x, but the 'value'
in this case is a reference to an object, not an object.

It is not correct to say that you "dispose the variable on the left
side ...". When you say "x.Dispose()", you are calling the Dispose
method of the object references by the variable x. The object is
being disposed, not the variable.
 
Jack,
Thanks again, you have just moved my knowledge up another notch.

Is there an easy way to find out whether an object is a "Value" object or a
"Reference" object, as now I understand the difference, I want to be sure
that I deal with my variables properly.

Siv
 
Jack,
I followed the link in one of Cor's posts and it was some stuff in the MSDN
site that discussed disposal of objects. On reading that and then follwoing
some other links I got the impresion that including a dispose method in your
class modules actually was not needed unless you had some unmanaged resources
to dispose of. In fact I get the impression that including a dispose method
actually slowed things down if there were no unmanaged resources?

Have I understood that correctly? Also, what are some examples of unmanaged
resources, I am again not sure how you identify those?

Siv
 
Jack,
Thanks again, you have just moved my knowledge up another notch.

Is there an easy way to find out whether an object is a "Value" object or a
"Reference" object, as now I understand the difference, I want to be sure
that I deal with my variables properly.

Siv

Look at the documentation. For example DateTime
(<http://msdn.microsoft.com/en-us/library/system.datetime.aspx>),
under Remarks it says "value type".

Another clue is that usually value items with multiple properties
don't allow you to change any of the properties - a new object must be
created instead.
 
Jack,
I followed the link in one of Cor's posts and it was some stuff in the MSDN
site that discussed disposal of objects. On reading that and then follwoing
some other links I got the impresion that including a dispose method in your
class modules actually was not needed unless you had some unmanaged resources
to dispose of. In fact I get the impression that including a dispose method
actually slowed things down if there were no unmanaged resources?

Have I understood that correctly? Also, what are some examples of unmanaged
resources, I am again not sure how you identify those?

Siv

Unmanaged resources are things like Windows handles (file handles, GDI
handles, etc.) - things that don't come from .NET.

Having Dispose does not slow anything down. Having a Finalizer does.
An object that implements Dispose often also implements a Finalizer. A
Finalizer is code that runs when the garbage collector frees the
object to take care of the case where the programmer did not call
Dispose - it effectively disposes the object at garbage collection
time.

For objects that have a Finalizer, the usual sequence is that the
programmer calls Dispose, which frees the unmanaged resources and (if
the object is coded correctly) tells the garbage collector that the
Finalizer does not have to be called. Should the programmer fail to
call Dispose, then the garbage collector will call the Finalizer
before releasing the object, which will then release the unmanaged
resources.

If the garbage collector has to call the Finalizer, that causes a
performance problem.

The bottom line is that if an object has a Finalizer and its Dispose
is not called, there will be a perfornamce impact. There are two
important reasons to call Dispose for objects that have a Finalizer.
First, to free unmanaged resources in a timely manner, and second to
prevent extra work for the garbage collector.

There are a couple of good articles on the garbage collector here:

# Jeffery Richter. Garbage Collection: Automatic Memory Management in
the Microsoft .NET Framework". MSDN Magazine, November 2000.
<http://msdn.microsoft.com/msdnmag/issues/1100/GCI/>
# Jeffery Richter. Garbage Collection - Part 2: Automatic Memory
Management in the Microsoft .NET Framework". MSDN Magazine, December
2000.
<http://msdn.microsoft.com/msdnmag/issues/1200/GCI2/>
 
Jack,
Thanks for pointing that out. It is not hugely obvious until you know the
meaning of that term. I would have expected a heading saying

Value or Reference Type: Value

or something similar near the top of the description of the object.

Thanks,

Siv
 
Back
Top