We use this class quite a bit for boilerplate / glue that allows web services and applications to call databases. This code is very important, and I'd like to ensure I'm getting the best performance possible.
Any and all feedback is welcome! If there is a better / more efficient way of doing something, please let me know.
Imports System.Data.SqlClient
Imports System.Data
Public Class MSSqlUtility
#Region "Data Access Utilities"
''' <summary>
''' Gets the data table.
''' </summary>
''' <param name="_command">The _command.</param>
''' <param name="_commandType">Type of the _command.</param>
''' <param name="_prmList">The parameter list.</param>
''' <returns>DataTable object - returns empty datatable if it failed</returns>
Public Shared Function GetDataTable(ByVal _command As String, ByVal _commandType As CommandType, Optional ByVal _prmList As ArrayList = Nothing) As DataTable
Dim cmd As SqlCommand = Nothing
Dim conn As SqlConnection = Nothing
Try
Using dt As New DataTable()
conn = New SqlConnection(GetConnectionString())
cmd = New SqlCommand(_command, conn)
cmd.CommandType = _commandType
If (_prmList IsNot Nothing) Then
For Each p As SqlParameter In _prmList
cmd.Parameters.Add(p)
Next
End If
If (conn.State <> ConnectionState.Open) Then
conn.Open()
End If
'Fill the datatable object
Using adapter As New SqlDataAdapter(cmd)
adapter.Fill(dt)
End Using
If (conn.State <> ConnectionState.Closed) Then
conn.Close()
End If
Return dt
End Using
Catch ex As Exception
LoggingUtility.LogError(ex, "MSSqlUtility.GetDataTable")
Return New DataTable()
Finally
cmd.Connection.Close()
cmd.Parameters.Clear()
cmd.Dispose()
conn.Dispose()
End Try
End Function
''' <summary>
''' Gets the data set.
''' </summary>
''' <param name="_command">The _command.</param>
''' <param name="_commandType">Type of the _command.</param>
''' <param name="_prmList">The _PRM list.</param>
''' <returns>DataSet object - empty if an error occurred</returns>
Public Shared Function GetDataSet(ByVal _command As String, ByVal _commandType As CommandType, Optional ByVal _prmList As ArrayList = Nothing) As DataSet
Dim cmd As SqlCommand = Nothing
Dim conn As SqlConnection = Nothing
Try
Using dt As New DataSet()
conn = New SqlConnection(GetConnectionString())
cmd = New SqlCommand(_command, conn)
cmd.CommandType = _commandType
If (_prmList IsNot Nothing) Then
For Each p As SqlParameter In _prmList
cmd.Parameters.Add(p)
Next
End If
If (conn.State <> ConnectionState.Open) Then
conn.Open()
End If
'Fill the DataSet object
Using adapter As New SqlDataAdapter(cmd)
adapter.Fill(dt)
End Using
If (conn.State <> ConnectionState.Closed) Then
conn.Close()
End If
Return dt
End Using
Catch ex As Exception
LoggingUtility.LogError(ex, "MSSqlUtility.GetDataSet")
Return New DataSet()
Finally
cmd.Connection.Close()
cmd.Parameters.Clear()
cmd.Dispose()
conn.Dispose()
End Try
End Function
''' <summary>
''' Gets the very first item returned by a query or command.
''' </summary>
''' <param name="_command">The _command.</param>
''' <param name="_commandType">Type of the _command.</param>
''' <param name="_prmList">The _PRM list.</param>
''' <returns>object - you will need to cast this appropriately. Returns -1 if an error occured.</returns>
Public Shared Function GetScalar(ByVal _command As String, ByVal _commandType As CommandType, Optional ByVal _prmList As ArrayList = Nothing) As Object
Dim cmd As SqlCommand = Nothing
Dim conn As SqlConnection = Nothing
Dim obj As New Object()
Try
conn = New SqlConnection(GetConnectionString())
cmd = New SqlCommand(_command, conn)
cmd.CommandType = _commandType
If (_prmList IsNot Nothing) Then
For Each p As SqlParameter In _prmList
cmd.Parameters.Add(p)
Next
End If
If (conn.State <> ConnectionState.Open) Then
conn.Open()
End If
obj = cmd.ExecuteScalar()
If (conn.State <> ConnectionState.Closed) Then
conn.Close()
End If
Catch ex As Exception
LoggingUtility.LogError(ex, "MSSqlUtility.GetScalar")
'return -1 to identify an error
Return -1
Finally
cmd.Connection.Close()
cmd.Parameters.Clear()
cmd.Dispose()
conn.Dispose()
End Try
Return obj
End Function
''' <summary>
''' Executes the SQL item.
''' </summary>
''' <param name="_command">The _command.</param>
''' <param name="_commandType">Type of the _command.</param>
''' <param name="_prmList">The _PRM list. This should be of SqlParameter type.</param>
Public Shared Sub ExecuteSqlItem(ByVal _command As String, ByVal _commandType As CommandType, Optional ByVal _prmList As ArrayList = Nothing)
Dim cmd As SqlCommand = Nothing
Dim conn As SqlConnection = Nothing
Try
conn = New SqlConnection(GetConnectionString())
cmd = New SqlCommand(_command, conn)
cmd.CommandType = _commandType
If (_prmList IsNot Nothing) Then
For Each p As SqlParameter In _prmList
cmd.Parameters.Add(p)
Next
End If
If (conn.State <> ConnectionState.Open) Then
conn.Open()
End If
cmd.ExecuteNonQuery()
If (conn.State <> ConnectionState.Closed) Then
conn.Close()
End If
Catch ex As Exception
LoggingUtility.LogError(ex, "MSSqlUtility.ExecuteSqlItem")
Finally
cmd.Connection.Close()
cmd.Parameters.Clear()
cmd.Dispose()
conn.Dispose()
End Try
End Sub
#End Region
End Class
To test the class, we use this automated test class. I have cleared the stored procedure and parameter names - you will need to adjust these to test the code above. This code is not what we are concerned with, but if you're adamant on code reviews, I suppose you can review this too :)
[TestMethod]
public void GetDataTableTest()
{
var procName = "your_stored_procedure_name";
var dt = MSSqlUtility.GetDataTable(procName, CommandType.StoredProcedure);
Assert.IsFalse(dt == null);
Assert.IsTrue(dt.Rows.Count > 0);
dt = null;
procName = "your_stored_procedure_name";
var prmList = new ArrayList();
prmList.Add(new SqlParameter("@parameter", value));
dt = MSSqlUtility.GetDataTable(procName, CommandType.StoredProcedure, prmList);
Assert.IsFalse(dt == null);
Assert.IsTrue(dt.Rows.Count > 0);
}
[TestMethod]
public void GetDataSetTest()
{
var procName = "your_stored_procedure_name";
DataSet ds = null;
ds = MSSqlUtility.GetDataSet(procName, CommandType.StoredProcedure);
Assert.IsFalse(ds == null);
Assert.IsFalse(ds.Tables[0] == null);
Assert.IsTrue(ds.Tables[0].Rows.Count > 0);
}
[TestMethod]
public void GetScalarTest()
{
var procName = "your_stored_procedure_name";
var prmList = new ArrayList();
prmList.Add(new SqlParameter("@parameter", value));
object result = null;
result = MSSqlUtility.GetScalar(procName, CommandType.StoredProcedure, prmList);
Assert.IsFalse(result == null);
int i = 0;
Int32.TryParse(result.ToString(), out i);
Assert.IsTrue(i > 0);
}
[TestMethod]
public void ExecuteSqlItemTest()
{
var procName = "your_stored_procedure_name";
var inputs = new ArrayList();
inputs.Add(new SqlParameter("@parameter", value));
inputs.Add(new SqlParameter("@parameter", value));
inputs.Add(new SqlParameter("@parameter", value));
inputs.Add(new SqlParameter("@parameter", value));
try
{
MSSqlUtility.ExecuteSqlItem(procName, CommandType.StoredProcedure, inputs);
//Pass the test. Assume the data manipulation was successful.
//Recommend verify the data changes in the database in addition to running this test.
Assert.IsTrue(true);
}
catch
{
//Something failed and went wrong. Fail the test.
Assert.IsTrue(false);
}
}