Reusability is the key to rapid application development in Visual Studio .NET, especially when it relates to data access via ADO.NET. This article discusses the use of a data access class that I wrote many months ago and use daily in every application I develop. For the sake of space, I have removed some of the methods and all error handling that relates specifically to an application.
I am providing the code for the class in both C# codeand VB.NET code, but for this article, the code that shows how to use the class is provided in C# only. I use both languages to develop applications, depending on the application and what it does. The class discussed in this article is using SQL Server objects, but I normally have methods for using OleDB objects as well as SqlClient objects. I have simply removed them for sake of space.
To call the class methods, you need to set up some module level variables, whether it is in a form or a class. Those variables are shown below. They provide an instantiation of the data access class, CDataAccess, along with a connection string, and connection object.
| private CDataAccessNS.CDataAccess oDA = new CDataAccessNS.CDataAccess(); private string ConnStr = "Data Source=MY-SQLSRV;"+ "Integrated Security=SSPI;" + "Initial Catalog=ProductTracking"; private SqlConnection Connection; |
| private void TestDataAccess() { try { // read from db using connect string DataTable dt = new DataTable(); string Sql = "Select count(*) from product_tracking"; int iRows = oDA.SendQuery(Sql, ref dt, ConnStr); Debug.WriteLine(dt.Rows[0].ItemArray[0]); // read from db using connection // this type of call would normally be used in a loop dt.Reset(); Connection = new SqlConnection(); if(oDA.OpenConnection(ConnStr, ref Connection) == false) { Debug.WriteLine("Open connection failed"); } else { iRows = oDA.SendQuery(Sql,ref dt, ref Connection); Debug.WriteLine(dt.Rows[0].ItemArray[0]); Connection.Close(); } // write to db using connect string Sql = "update product_tracking "; Sql += "set product_class = 'Test' "; Sql += "where product_number = 'PR-01-2345' "; string ErrMsg = String.Empty; iRows = oDA.SendActionSql(Sql, ConnStr, ref ErrMsg); if (iRows == 0) { Debug.WriteLine(ErrMsg); } // write to db using connection // this type of call would normally be used in a loop // and use the same connection repeatedly to enhance // performance. if(oDA.OpenConnection(ConnStr, ref Connection) == false) { Debug.WriteLine("Open connection failed"); } else { Sql = "update product_tracking "; Sql += "set product_class = 'Test2' "; Sql += "where job_number = 'PR-0102345' "; ErrMsg = String.Empty; iRows = oDA.SendActionSql(Sql, Connection, ref ErrMsg); if (iRows == 0) { Debug.WriteLine(ErrMsg); } } } catch(System.Exception ex) { Debug.WriteLine(ex.ToString()); } } |
| using System; using System.Data.SqlClient; using System.Data; namespace CDataAccessNS { public class CDataAccess { private SqlCommand dbCmdSS; private SqlDataAdapter daSS; private SqlConnection ConnSS; // Returns number of rows affected // dt will be filled // Returns -2 on any error public int SendQuery(string Sql, ref DataTable dt, string ConnectString) { try { ConnSS = new SqlConnection(ConnectString); dbCmdSS = new SqlCommand(Sql, ConnSS); daSS = new SqlDataAdapter(dbCmdSS); daSS.Fill(dt); return dt.Rows.Count; } catch { return -2; } } // overloaded function that accepts a connection // and does not connnect and disconnect // used when program is going to do numerous hits // to database in a loop // Returns number of rows affected // dt will be filled // returns -2 on any error public int SendQuery(string Sql, ref DataTable dt, ref SqlConnection Connection) { try { dbCmdSS.CommandText = Sql; dbCmdSS.Connection= Connection; daSS = new SqlDataAdapter(dbCmdSS); daSS.Fill(dt); return dt.Rows.Count; } catch { return -2; } } // opens a connection to the database // and return true if successful public bool OpenConnection(string ConnStr, ref SqlConnection Conn) { try { Conn.ConnectionString = ConnStr; if(Conn.State != ConnectionState.Open) { Conn.Open(); return true; } return true; } catch { return false; } } // Executes the passed action sql. returns // nbr rows affected if successful // otherwise returns -1 and sErr will // contain ex.tostring public int SendActionSql(string Sql, SqlConnection Conn, ref string ErrMsg) { try { int RowsAffected = 0; dbCmdSS = new SqlCommand(); dbCmdSS.CommandText=Sql; dbCmdSS.Connection=Conn; RowsAffected = dbCmdSS.ExecuteNonQuery(); return RowsAffected; } catch(System.Exception ex) { ErrMsg=ex.ToString(); return -1; } } // Executes the passed action sql. returns // nbr rows affected if successful // otherwise returns -1 and sErr will // contain ex.tostring public int SendActionSql(string Sql, string ConnString, ref string ErrMsg) { try { if(OpenConnection(ConnString, ref ConnSS)!=true) { ErrMsg = "Unable to open connection"; return -1; } int RowsAffected = 0; dbCmdSS = new SqlCommand(); dbCmdSS.CommandText=Sql; dbCmdSS.Connection=ConnSS; RowsAffected = dbCmdSS.ExecuteNonQuery(); ConnSS.Close(); return RowsAffected; } catch(System.Exception ex) { ErrMsg = ex.ToString(); return -1; } } public CDataAccess() { } } } |
| '**************************************** '* Purpose: Reusable methods for data access '* Author: Les Smith '* Date Created: 09/17/2002 at 02:15:16 '**************************************** Imports System.Data.SqlClient Imports System.Windows.Forms.Application Public Class CDataAccess Dim dbCmdSS As New SqlCommand() Dim daSS As New SqlDataAdapter() Dim ConnSS As New SqlConnection() Dim mytrans As SqlTransaction ' overloaded function that accepts a connection ' and does not connnect and disconnect ' used when program is going to do numerous hits ' to database in a loop ' Returns number of rows affected ' If error, ErrNum and ErrMsg will have the ' respective values ' dt will be filled ' Returns -1 if connection can't be made ' returns -2 on any other error Public Overloads Function SendQuery(ByVal Sql As String, _ ByRef dt As DataTable, _ ByRef Connection As SqlConnection) As Integer Try dbCmdSS.CommandText = Sql dbCmdSS.Connection = Connection daSS = New SqlDataAdapter(dbCmdSS) daSS.Fill(dt) Return dt.Rows.Count Catch ex As System.Exception End Try End Function ' Returns number of rows affected ' If error, ErrNum and ErrMsg will have the ' respective values ' dt will be filled ' Returns -1 if connection can't be made ' returns -2 on any other error ' SSSql = "S" for SqlSrvr or "O" for Sql ' This function supports Sql Public Overloads Function SendQuery(ByVal Sql As String, _ ByRef dt As DataTable, _ ByVal ConnectString As String) As Integer Try If Not Me.OpenConnection(ConnectString, ConnSS) Then Return -1 ' can't connect to db End If Me.dbCmdSS.CommandText = Sql dbCmdSS.Connection = ConnSS daSS = New SqlDataAdapter(dbCmdSS) daSS.Fill(dt) ConnSS.Close() Return dt.Rows.Count Catch ex As System.Exception Return -1 End Try End Function '' Executes the passed action sql. Returns the following: '' iRowsAffected if successful '' -1 = unique constraint violation '' -2 = locked and retries exceeded '' -3 = other error (ErrMsg will contain err.description) Public Overloads Function SendActionSql(ByVal Sql As String, _ ByVal ConnectString As String, _ ByRef ErrMsg As String) _ As Integer Dim iStart As Integer Dim iRowsAffected As Integer Dim dbCmdSS As New SqlCommand() Dim ConnSS As New SqlConnection() Dim mytrans As SqlTransaction Dim errCnt As Integer ErrMsg = "" Try If Not Me.OpenConnection(ConnectString, ConnSS) Then ErrMsg = "Unable to connect to " & ConnectString Return -3 End If mytrans = ConnSS.BeginTransaction() dbCmdSS.CommandText = Sql dbCmdSS.Connection = ConnSS dbCmdSS.Transaction = mytrans iRowsAffected = dbCmdSS.ExecuteNonQuery mytrans.Commit() Return iRowsAffected Catch ex As System.Exception ErrMsg = ex.ToString Return -1 End Try End Function '' Executes the passed action sql. Returns the following: '' iRowsAffected if successful otherwise -1 with exception in ErrMsg Public Overloads Function SendActionSql(ByVal Sql As String, _ ByRef Connection As SqlConnection, _ ByRef ErrMsg As String) _ As Integer Dim iStart As Integer Dim iRowsAffected As Integer Dim dbCmd As New SqlCommand() Dim Conn As New SqlConnection() Dim errCnt As Integer Try ErrMsg = String.Empty dbCmd.CommandText = Sql dbCmd.Connection = Connection iRowsAffected = dbCmd.ExecuteNonQuery Return iRowsAffected Catch ex As System.Exception ErrMsg = ex.ToString Return -1 End Try End Function ' opens a connection to the database and return true if successful Public Overloads Function OpenConnection(ByVal ConnStr As String, ByRef Conn As SqlConnection) As Boolean Dim i As Integer Try Do Conn.ConnectionString = ConnStr Conn.Open() Return True Catch Return False End Try End Function End Class |