Data Access Layer

Introduction
We often read or hear about n-tier applications, layers e.t.c. The benefits of implementing such a logic in the code is not a subject of this article, but most of developers are aware of that. Since my beginning in .net I had in mind that maybe I could develop a Data Access Layer so I would not have to ever code that layer again and only code stored rocedures and the layer just above the data access layer.

My Solution
The first part of my solution comes with this article. I developed in the beginning just the basic parts of the layer and functions that retrieve records, datasets, update tables, delete records.
My basic Data Access Layer consists from 3 classes (AccessingData, Field, FieldsCollection).

Field Class
The field class is used to represent a field from a table (and to later add it to a collection and pass it to the command). It simply has 4 properties ColumnName,ColumnType, ColumnLength, ColumnValue (each the desired type)
This is the code.

Public Class Field
    Private _columnName As String = ""
    Private _columnType As SqlDbType = SqlDbType.VarChar
    Private _columnLength As Integer = 0
    Private _columnValue As Object
    Public Property ColumnName() As String
        Get
            Return _columnName
        End Get
        Set(ByVal Value As String)
            _columnName = Value
        End Set
    End Property

    Public Property ColumnType() As SqlDbType
        Get
            Return _columnType
        End Get
        Set(ByVal Value As SqlDbType)
            _columnType = Value
        End Set
    End Property
    Public Property ColumnLength() As Integer
        Get
            Return _columnLength
        End Get
        Set(ByVal Value As Integer)
            _columnLength = Value
        End Set
    End Property

    Public Property ColumnValue() As Object
        Get
            Return _columnValue
        End Get
        Set(ByVal Value As Object)
            _columnValue = Value
        End Set
    End Property

    Public Sub New(ByVal colName As String, ByVal colType As SqlDbType, _
                       
ByVal colValue As Object, ByVal colLength As Integer)
        Me.ColumnName = colName
        Me.ColumnType = colType
        Me.ColumnLength = colLength
        Me.ColumnValue = colValue
    End Sub
End Class


Fields Collection Class
This class is simply used as a collection of fields. Nothing so much special abou that. Here is the code:

Public Class FieldsCollection
    Inherits System.Collections.CollectionBase

    Public Sub Add(ByVal objItemToAdd As Field)
        Me.List.Add(objItemToAdd)
    End Sub
    Public ReadOnly Property Item(ByVal iIndex As Integer) As Field
        Get
            Return Me.List(iIndex)
        End Get
    End Property
End Class

Accessing Data Class
This class is the most important one. Here we have properties for the connection, the connection string, the sqlcommand, the transaction and the functions to retrieve datasets (whole table - Get_Dataset), to retrieve specific record by id (Get_record_byId), the sub to delete record (Delete_record) and the sub to update records (Update_Record).
We can set if we want transaction or not from the above layer. If we do not want to then this layer opens connections does the job and then closes the connection.
Here is the code:

Imports System.Data.SqlClient
Public Class AccessingData
    Private _conn As New SqlConnection
    Private _trans As SqlTransaction
    Private _connectionstring As String = System.Configuration.ConfigurationSettings.AppSettings("SQLconn")
    Private _command As New SqlCommand
    Public Property SqlCommand() As SqlCommand
        Get
            Return _command
        End Get
        Set(ByVal Value As SqlCommand)
            _command = Value
        End Set
    End Property
    Public Property SqlConnection() As SqlConnection
        Get
            Return _conn
        End Get
        Set(ByVal Value As SqlConnection)
            _conn = Value
        End Set
    End Property
    Public Property Transaction() As SqlTransaction
        Get
            Return _trans
        End Get
        Set(ByVal Value As SqlTransaction)
            _trans = Value
        End Set
    End Property
    Public Property SqlConnectionString() As String
        Get
            Return _connectionstring
        End Get
        Set(ByVal Value As String)
            _connectionstring = Value
        End Set
    End Property
    Public Function Get_Dataset(ByVal storedprocedurename As String, _
                            
ByVal datatable As String) As DataSet
        Dim sqlDataAdapter As New SqlDataAdapter
        Try
            sqlDataAdapter.SelectCommand = New SqlCommand
            If _conn.ConnectionString = "" Then
               
_conn.ConnectionString = _connectionstring
            End If
            sqlDataAdapter.SelectCommand.Connection = _conn
            If Not _conn.State = ConnectionState.Open Then
                _conn.Open()
            End If
           
sqlDataAdapter.SelectCommand.CommandText = storedprocedurename
           
sqlDataAdapter.SelectCommand.CommandType = CommandType.StoredProcedure
            If Not IsNothing(_trans) Then
               
sqlDataAdapter.SelectCommand.Transaction = _trans
            End If

            'sqlDataAdapter.SelectCommand.ExecuteNonQuery()
            Dim myDataSet As DataSet = New DataSet
            sqlDataAdapter.Fill(myDataSet, datatable)
            Return myDataSet
        Catch ex As Exception
            Throw ex
        Finally
            If IsNothing(_trans) Then
                _conn.Close()
            End If

        End Try
    End Function
    Public Function Get_record_byID(ByVal myField As Field, ByVal storedprocedurename As String, _
                               
ByVal datatable As String) As DataSet
        Dim sqlDataAdapter As New SqlDataAdapter
        Try
            sqlDataAdapter.SelectCommand = New SqlCommand
            If _conn.ConnectionString = "" Then
               
_conn.ConnectionString = _connectionstring
            End If

            sqlDataAdapter.SelectCommand.Connection = _conn
            If Not _conn.State = ConnectionState.Open Then
                _conn.Open()
            End If

           
sqlDataAdapter.SelectCommand.CommandText = storedprocedurename
           
sqlDataAdapter.SelectCommand.CommandType = CommandType.StoredProcedure
            If Not IsNothing(_trans) Then
               
sqlDataAdapter.SelectCommand.Transaction = _trans
            End If
            'Parameters
            Dim myparam As SqlParameter
            myparam = New SqlParameter("@" & myField.ColumnName, _
                                                               
myField.ColumnType, myField.ColumnLength)
            myparam.Value = myField.ColumnValue
            myparam.Direction = ParameterDirection.Input
            sqlDataAdapter.SelectCommand.Parameters.Add(myparam)

            sqlDataAdapter.SelectCommand.ExecuteNonQuery()
            Dim myDataSet As DataSet = New DataSet
            sqlDataAdapter.Fill(myDataSet, datatable)
            Return myDataSet
        Catch ex As Exception
            Throw ex
        Finally
            If IsNothing(_trans) Then
                _conn.Close()
            End If
        End Try
    End Function
    Public Sub Delete_record(ByVal myField As Field, _
                               
ByVal storedprocedure As String)

        Dim mycommand As New SqlCommand
        mycommand.CommandType = CommandType.StoredProcedure
        Try
            mycommand.Connection = _conn
            If _conn.ConnectionString = "" Then
               
_conn.ConnectionString = _connectionstring
            End If
            If Not IsNothing(_trans) Then
                mycommand.Transaction = _trans
            End If
            mycommand.CommandText = storedprocedure

            If Not _conn.State = ConnectionState.Open Then
                _conn.Open()
            End If

            'Parameters
            Dim myparam As SqlParameter
            myparam = New SqlParameter("@" & myField.ColumnName, _
                                                               
myField.ColumnType, myField.ColumnLength)
            myparam.Value = myField.ColumnValue
            myparam.Direction = ParameterDirection.Input
            mycommand.Parameters.Add(myparam)

            mycommand.ExecuteNonQuery()
        Catch ex As Exception
            If IsNothing(_trans) Then
                _conn.Close()
            End If
        End Try
    End Sub
    Public Sub Update_Record(ByVal storedprocedure As String, _
                               
ByVal myFieldsCollection As FieldsCollection)
        Try
            Dim mycommand As New SqlCommand
            mycommand.CommandType = CommandType.StoredProcedure
            mycommand.CommandText = storedprocedure
            mycommand.Connection = _conn
            If _conn.ConnectionString = "" Then
               
_conn.ConnectionString = _connectionstring
            End If
            If Not IsNothing(_trans) Then
                mycommand.Transaction = _trans
            End If
            If Not _conn.State = ConnectionState.Open Then
                _conn.Open()
            End If
            'Parameters
            Dim myparam As SqlParameter
            For i As Integer = 0 To myFieldsCollection.Count - 1
                Dim obj As Field
                obj = myFieldsCollection.Item(i)

               
myparam = New SqlParameter("@" & obj.ColumnName, _
                                                               
obj.ColumnType, obj.ColumnLength)
                myparam.Value = obj.ColumnValue

               
myparam.Direction = ParameterDirection.Input
                mycommand.Parameters.Add(myparam)
            Next
            mycommand.ExecuteNonQuery()
        Catch ex As Exception
            Throw ex
        Finally
            If IsNothing(_trans) Then
                _conn.Close()
            End If
        End Try
    End Sub
End Class

To use all of the above we simply need stored procedures to retrieve values , insert records e.t.c.
Let us use the Northwind database. Here is a stored procedure for updating the Region table.




CREATE  PROCEDURE DBO.UPDATE_REGION
@REGIONDESCRIPTION VARCHAR (50),
@REGION_ID INT

AS
BEGIN
    UPDATE REGION
        SET REGIONDESCRIPTION = @REGIONDESCRIPTION
    WHERE REGIONID = @REGION_ID
END
GO

 

Wrap it up!
To use all of the above we reference the dll in our project. Then for example to update the Region table we use the following code:

Dim mx As New AccessingData
Try
       Dim myField1 As New Field("REGIONDESCRIPTION", SqlDbType.NChar, "REGION1", 50)
       Dim myCollection As New FieldsCollection
       myCollection.Add(myField1)
       myField1 = Nothing
       Dim myField2 As New Field("REGION_ID", SqlDbType.Int, 1, 4)
       myCollection.Add(myField2)
       myField2 = Nothing

       mx.Update_Record("UPDATE_REGION", myCollection)
Catch ex As Exception

End Try

We could easily use transaction simply by adding this code before the "Update_record" line:


'With transaction
mx.SqlConnection.ConnectionString = mx.SqlConnectionString
mx.SqlConnection.Open()
mx.Transaction = mx.SqlConnection.BeginTransaction()
'But after that dont forget to close the connection:
mx.SqlConnection.Close()


Comming Next
In the next article I will go a little bit deeper and use custom attributes :-)

 

Share


Έχουν δημοσιευτεί Παρασκευή, 21 Οκτωβρίου 2005 12:26 μμ από το μέλος zeon

Ενημέρωση για Σχόλια

Αν θα θέλατε να λαμβάνετε ένα e-mail όταν γίνονται ανανεώσεις στο περιεχόμενο αυτής της δημοσίευσης, παρακαλούμε γίνετε συνδρομητής εδώ

Παραμείνετε ενήμεροι στα τελευταία σχόλια με την χρήση του αγαπημένου σας RSS Aggregator και συνδρομή στη Τροφοδοσία RSS με σχόλια

Σχόλια:

 

cap έγραψε:

Interesting experiment, although a bit too generic for my taste. Allows for fast development where performance is not an issue, so I'd think it's good enough to be used in a number of cases. Keep up the good work!
Οκτωβρίου 24, 2005 11:39 πμ
 

Χρήστος Γεωργακόπουλος έγραψε:

At Public Function Get_Dataset, why do you execute the same command twice;

sqlDataAdapter.SelectCommand.ExecuteNonQuery()
Dim myDataSet As DataSet = New DataSet
sqlDataAdapter.Fill(myDataSet, datatable)
Οκτωβρίου 24, 2005 2:36 μμ
 

zeon έγραψε:

Thanks! I have missed that one :-) . Now the first line is a comment (so other users can see what you meant).
Οκτωβρίου 24, 2005 3:05 μμ
 

axaros έγραψε:

Very good effort Zeon.
I would only nug about the fact that you've designed it as SQL Server specific.
I am looking for a generic (and extensible) mid tier.
Οκτωβρίου 31, 2005 9:57 πμ

Ποιά είναι η άποψή σας για την παραπάνω δημοσίευση;

(απαιτούμενο)
απαιτούμενο
προαιρετικό
απαιτούμενο
ÅéóÜãåôå ôïí êùäéêü:
CAPTCHA Image