.NET Dataset Disposal
Foo1 or Foo2?
Please help! I have been searching for a definitive and authoritative answer on the dataset disposal issue below. My client insists that there is a memory leak in Foo1() since the dataset is not disposed. He would like any functions returning datasets to be rewritten as Foo2() which “properly” disposes of the dataset. [Sample code is below].
I disagree. I believe the following to be true. Please correct me if I am wrong. Please confirm if I am right.
- Is it completely unnecessary to dispose of a dataset in an intermediate function (such as Foo()) which merely gets a reference to a dataset and returns that reference to the caller.
- You can argue that you never have to dispose of the dataset.
- The GC will handle this automatically.
- The dataset dispose is only there as a byproduct of inheritance from MarshalByValueComponent - since a dataset contains no unmanaged resources dispose doesn’t do anything anyway.
- The counter argument is that dispose should be called for any class that implements it. Even though dataset dispose does nothing now Microsoft reserves the right to change that in the future.
- Not only is disposing of the dataset in the intermediate function unnecessary – It is dangerous. Suppose dispose actually did clear the memory? There would be nothing to return! The data would be wiped out. This is actually the case if this were a dataview instead.
- If dispose should be called at all, it is the caller’s responsibility. The root function should dispose of the dataset once it is finished using it. There is no need to keep disposing of returned datasets through any number of intermediate calls.
Questions
- Is there still any value in setting the variable to Nothing once it is disposed? This is done presumably to aid the GC in knowing that a variable is no longer needed.
- Would there be any difference in the dataset disposal in difference .NET frameworks? FYI - This code is for a website ASP.NET 3.5 Framework 2.0.
- Is there any way to prove this with a simple test?
For whatever reason, I cannot find a satisfactory answer for all of this either on the internet forums or in Microsoft’s own documentation.
Thank you for your response.
------------------------ Sample Code --------------------------------
Sub Main()
Dim dsAsDataSet
Try
ds = Foo1("select stuff from MyTable")
DisplayStuff(ds)
Finally
'If the dataset should be disposed at all...It should be done here
'once the caller is finished with it.
'Is disposing here even necessary? Shouldn’t the GC handle it anyway?
ds.Dispose()
ds =Nothing 'Is it necessary to set this to nothing?
EndTry
EndSub
Function Foo1(sqlAsString)AsDataSet
Return GetDataSet(sql)
EndFunction
Function Foo2(sqlAsString)
Dim dsAsDataSet
Try
ds = GetDataSet(sql)
Return ds
Finally
'Is this code necessary? We're just returning a reference to a dataset.
ds.Dispose()
ds =Nothing
EndTry
EndFunction
Function GetDataSet(sqlAsString)
Dim dsAsNewDataSet
Using db =New SqlConnection("SERVER=MyServer;DATABASE=MyDatabase;")
db.Open()
Using adaptAsNewSqlDataAdapter(sql, db)
adapt.Fill(ds)
EndUsing
EndUsing
Return ds
EndFunction