Member_2_7717371
asked on
Opening and Closing Connections and Data Adapters
In virtually all of my coding (vb.net, Visual Studio 2013, SQL Server 2012) I retrieve data from my SQL Server database based on the below example. My intent of this question is to see if this is a proper way of retrieving the data and closing the connections/disposing of objects. I want to ensure that there is not a chance of leaving a connection open in error (i.e. network interruption)
Thanks in advance for any input.
In a data layer:
Public Class DB_GetSomeData
Pubic Shared Function GetData (ByVal EquipmentID as Integer)
'Specify Connection to DB
Dim connection As SqlConnection = Database.Connection 'This goes to another data layer specifying the appropriate DB
Dim selectStatement as String = "Select CustomerName from Equipment where EquipmentID = " & EquipmentID & " "
Dim DataAdapter as New SqlDataAdapter(selectState ment, connection)
Dim dt as New DataTable
Try
dt.Clear()
connection.open()
DataAdapter.Fill(dt)
connection.Close()
Catch ex as Exception
connection.Close() 'Close just in case still open
MessageBox.Show(ex.Message )
End Try
Return dt
End Function
Thanks in advance for any input.
In a data layer:
Public Class DB_GetSomeData
Pubic Shared Function GetData (ByVal EquipmentID as Integer)
'Specify Connection to DB
Dim connection As SqlConnection = Database.Connection 'This goes to another data layer specifying the appropriate DB
Dim selectStatement as String = "Select CustomerName from Equipment where EquipmentID = " & EquipmentID & " "
Dim DataAdapter as New SqlDataAdapter(selectState
Dim dt as New DataTable
Try
dt.Clear()
connection.open()
DataAdapter.Fill(dt)
connection.Close()
Catch ex as Exception
connection.Close() 'Close just in case still open
MessageBox.Show(ex.Message
End Try
Return dt
End Function
Using con As New SqlConnection(conString)
Dim cmd As SqlCommand = New SqlCommand
With cmd
.CommandType = CommandType.StoredProcedure
.CommandText = "Your stored procedure name here"
.Connection = con
.Connection.Open()
End With
Dim reader As SqlDataReader
reader = cmd.ExecuteReader
While reader.Read
' Do something with your data here...
End While
reader.Close()
End Using
I generally use stored procedures when possible, rather than passing the query as a string. My understanding is that's less vulnerable to SQL Injection attacks... How you're using the data once you execute the query is up to you. You can fill an ADO table using the fill method you're using or you can use a SqlDataReader to iterate through the returned records like I'm showing above. Either way, if you use the "Using" method, that should automatically close the connections for you.
ASKER
Ok, so based on the input is the below coding better? If so, why is it better then my original code. Is there an advantage to updating all of database calls this way (I have a lot of them)? Will everything be disposed of properly this way -- even if there is a network interruption? Thanks.
Imports System.Data.SqlClient
Public Class DB_SupplyReview_ContractSu pplyHistor yAllItems
Public Shared Function GetData(ByVal ContractID As Integer)
Dim connection As String = Company_DB_Using.GetConnec tion
Using con As New SqlConnection(connection)
''Create Select Statement
Dim selectStatement As String _
= "DECLARE @RC int " _
& "DECLARE @ContractID int = " & ContractID & " " _
& "EXECUTE @RC = cu_Todd_IMS_Supply_Orders_ Contract_P rofitabili ty_SupplyH istoryAllI tems @ContractID "
Dim DataAdapter As New SqlDataAdapter(selectState ment, connection)
Dim dt As New DataTable
Try
dt.Clear()
DataAdapter.Fill(dt)
Catch ex As Exception
MessageBox.Show(ex.Message )
End Try
Return dt
End Using
End Function
End Class
Imports System.Data.SqlClient
Public Class DB_SupplyReview_ContractSu
Public Shared Function GetData(ByVal ContractID As Integer)
Dim connection As String = Company_DB_Using.GetConnec
Using con As New SqlConnection(connection)
''Create Select Statement
Dim selectStatement As String _
= "DECLARE @RC int " _
& "DECLARE @ContractID int = " & ContractID & " " _
& "EXECUTE @RC = cu_Todd_IMS_Supply_Orders_
Dim DataAdapter As New SqlDataAdapter(selectState
Dim dt As New DataTable
Try
dt.Clear()
DataAdapter.Fill(dt)
Catch ex As Exception
MessageBox.Show(ex.Message
End Try
Return dt
End Using
End Function
End Class
In a nutshell, you can use the "Using" block with any object that implements IDisposable, and it should automatically dispose of the resources used by that object when you hit the End Using statement (when you're done 'using' it). More on that here. The SqlConnection class inherits DbConnection, which implements IDisposable. Likewise, the SqlCommand and DataTable classes inherit classes which implement IDisposable, so you can use Using blocks with them as well (as Scott showed in his post). The upside to using "Using" blocks is that you don't need to explicitly call "close" or "dispose", whereas you might otherwise have to do so in multiple places depending on the complexity of your code. It will automatically close connections and dispose of resources as soon as you're done using the object.
If your goal is to provide a ContactID and have your function return a Datatable, then this would probably be the "best" way:
That said, it looks like your Stored Procedure returns an Integer, which would result in the example code above erroring out.
Public Shared Function GetData(ByVal ContractID As Integer) As Datatable
Try
Using con As New SqlConnection(Company_DB_Using.GetConnection)
''Create Select Statement
Dim selectStatement As String _
= "DECLARE @RC int " _
& "DECLARE @ContractID int = " & ContractID & " " _
& "EXECUTE @RC = cu_Todd_IMS_Supply_Orders_Contract_Profitability_SupplyHistoryAllItems @ContractID "
con.Open
Using cmd As New sqlCommand
cmd.Connection = con
Dim dt As New Datatable
dt.Load(cmd.ExecuteReader)
If dt.Rows.Count>0 Then
Return dt
Else
Return Nothing
End If
End Using
End Using
Catch ex At Exception
Messagebox.Show("Error in GetData: " & ex.Tostring)
Return Nothing
End Try
End Function
That said, it looks like your Stored Procedure returns an Integer, which would result in the example code above erroring out.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
I'm going to mark as complete, but it appears as if the consensus is that Using is the best and I should use ExecuteReader instead of DataAdapter.fill. For my understanding can you please tell me why these are better? Thanks
ASKER
Thanks to both.
If u'r using datareader asynchroneously (ie. While Reader.Read ...) reader is faster and use less memory. If u'r using datatable.load method on datareader it's slower then DataAdapter.Fill(). See this.
Using con As New SQLConnection(YourConnecti
con.Open
Using cmd As New SQLCommand
cmd.Connection= con
cmd.CommandText = "blah blah"
Using dt As New Datatable
dt.Load(cmd.ExecuteReader)
For each dtr As Datarow in dt.Rows
<loop here
Next
End Using
End Using
End Using
The Using structure will ensure your connection and command objects are disposed of properly.