title: Datasets and Memory leaks
body: <p>I am trying to figure out the best way to use a <code>DataSet</code>/<code>DataTable</code> and cleaning up properly afterwards.</p>
  
  <p>I am a little puzzled as to what causes memory to be released. I tested my theory with a  test application where I populated the same <code>DataTable</code> multiple times in a loop and looking at Windows' Task Manager for the memory footprint after 3 forced GC collects.</p>
  
  <p>What I found is that:</p>
  
  <ol>
  <li><p>If I did not call <code>Clear</code> or <code>Dispose</code>, or set the <code>DataTable</code> variable to <code>Nothing</code>, the final memory consumption in Task Manager was about 30k.</p></li>
  <li><p>If I just set the variable to <code>Nothing</code> inside the loop, the final memory was about 15k.<br>
  Question: Why does setting the variable to <code>Nothing</code> make a difference?</p></li>
  <li><p>If I called only the <code>Dispose</code> method inside the loop, the final memory was about 19k.</p></li>
  <li><p>If I called only <code>Clear</code> inside the loop, the final memory was about 16.5k. In fact, it did not change even after the <code>GC.Collect</code>.</p></li>
  </ol>
  
  <p>I would really appreciate if someone can share what is the best way to use and cleanup <code>DataSet</code>s when no longer needed.</p>
  
  <p>Sample code is shown below.</p>
  
  <pre><code>Imports System.Data.SqlClient;
  Public Class Form1
  
      Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
          Test()
  
          GC.Collect()
          GC.Collect()
          GC.Collect() 'Throw in one more 
      End Sub
  
  
      Private Sub Test()
          Dim oDA As SqlDataAdapter = Nothing
          Dim oConn As SqlConnection = Nothing
          Dim oCommand As SqlCommand = Nothing
          Dim ods As DataSet = Nothing
          Dim oDt As DataTable = Nothing
          Try
              oConn = New SqlConnection("Server=Myserv;Database=myDB;UserId=myuserid;Password=mypassword;")
              oCommand = New SqlCommand("Select  * from Users", oConn)
              oConn.Open()
              ods = New DataSet
  
              oDA = New SqlDataAdapter(oCommand)
  
              For i As Integer = 0 To 50
                  oDA.Fill(ods)
                  oDt = ods.Tables(0)
                  'oDt.Clear()
                  'oDt.Dispose()
                  oDt = Nothing
              Next
          Catch ex As Exception
              MessageBox.Show(ex.ToString)
          Finally
              ods.Clear()
              ods = Nothing
              oConn.Close()
              oDA = Nothing
          End Try
      End Sub
  End Class
  </code></pre>
  
  <p>Edit: I am looking for best practices for managing memory of <code>DataSet</code>s and/or <code>DataTable</code>s that are passed around, where the creating method is not necessarily tasked with cleaning up the memory. Also, why does setting an object/variable to <code>Nothing</code> within a function performs differently than just letting it go out of scope.</p>