Take the following example...
Using cn As New SqlConnection(ConnectionString)
Try
Dim cmd As SqlCommand = New SqlCommand
With cmd
.Connection = cn
.Connection.Open()
.CommandText = "dbo.GetCustomerByID"
.CommandType = CommandType.StoredProcedure
.Parameters.Add("@CustomerID", SqlDbType.Int, 4)
.Parameters("@CustomerID").Value = CustomerID
End With
da = New SqlDataAdapter(cmd)
da.Fill(ds, "Customer")
Catch ex As Exception
End Try
End Using
From my research today is sounds as though this is basically okay but the SqlCommand is not being disposed of.
Question -> Which of the following examples is the best way to deal with this?
Example 2 - Dispose manually
Using cn As New SqlConnection(ConnectionString)
Try
Dim cmd As SqlCommand = New SqlCommand
With cmd
.Connection = cn
.Connection.Open()
.CommandText = "dbo.GetCustomerByID"
.CommandType = CommandType.StoredProcedure
.Parameters.Add("@CustomerID", SqlDbType.Int, 4)
.Parameters("@CustomerID").Value = CustomerID
End With
da = New SqlDataAdapter(cmd)
cmd.Dispose()
da.Fill(ds, "Customer")
Catch ex As Exception
End Try
End Using
Example 3 - Automatic disposing with the Using statement
Using cn As New SqlConnection(ConnectionString)
Try
Using cmd As New SqlCommand
With cmd
.Connection = cn
.Connection.Open()
.CommandText = "dbo.GetCustomerByID"
.CommandType = CommandType.StoredProcedure
.Parameters.Add("@CustomerID", SqlDbType.Int, 4)
.Parameters("@CustomerID").Value = CustomerID
End With
da = New SqlDataAdapter(cmd)
da.Fill(ds, "Customer")
End Using
Catch ex As Exception
End Try
End Using
Example 4 - The same as example 3 but the Try/Catch is within the Using - does this make a difference?
Using cn As New SqlConnection(ConnectionString)
Using cmd As New SqlCommand
Try
With cmd
.Connection = cn
.Connection.Open()
.CommandText = "dbo.GetCustomerByID"
.CommandType = CommandType.StoredProcedure
.Parameters.Add("@CustomerID", SqlDbType.Int, 4)
.Parameters("@CustomerID").Value = CustomerID
End With
da = New SqlDataAdapter(cmd)
da.Fill(ds, "Customer")
Catch ex As Exception
End Try
End Using
End Using
Example 5 - The same as example 4 but the CommandText and cn are specified in the Using Statement - What advantage does this have?
Using cn As New SqlConnection(ConnectionString)
Using cmd As New SqlCommand("GetCustomerByID", cn)
Try
With cmd
.Connection.Open()
.CommandType = CommandType.StoredProcedure
.Parameters.Add("@CustomerID", SqlDbType.Int, 4)
.Parameters("@CustomerID").Value = CustomerID
End With
da = New SqlDataAdapter(cmd)
da.Fill(ds, "Customer")
Catch ex As Exception
End Try
End Using
End Using
Example 6 - The same as example 5 but the connection is opened on cn instead of cmd. Is it better to open the connection on cmd if only one stored procedure is to be executed?
Using cn As New SqlConnection(ConnectionString)
cn.Open()
Using cmd As New SqlCommand("GetCustomerByID", cn)
Try
With cmd
.Connection = cn
.CommandType = CommandType.StoredProcedure
.Parameters.Add("@CustomerID", SqlDbType.Int, 4)
.Parameters("@CustomerID").Value = CustomerID
End With
da = New SqlDataAdapter(cmd)
da.Fill(ds, "Customer")
Catch ex As Exception
End Try
End Using
End Using
The DataAdapter.Fill command will open and close the connection itself, so you don't need the cmd.Connection.Open()
. (Ref: the remarks section in http://msdn.microsoft.com/en-us/library/377a8x4t.aspx .)
Using Using
for the SqlConnection has the effect of calling .Close
on it for you.
The variable cmd
becomes eligible for garbage collection once it is out of scope (or earlier if .NET determines it isn't going to be used again).
In your example 2, I'm not sure it's such a good idea to dispose of the cmd before the DataAdapter has used it.
[Information from user "JefBar Software Services" in Should I call Dispose on a SQLCommand object? ] At the time of writing, calling .Dispose
on an SqlCommand
has no effect because of the code in its constructor:
public SqlCommand() : base() {
GC.SuppressFinalize(this);
}