HomeASP.NET Developing a Data Access Layer for Sybase ...
Developing a Data Access Layer for Sybase using ADO.NET: Working With Stored Procedures
This article is third and last in a series focusing on developing a simple DAL (Data Access Layer) for any database using ADO.NET. In this series, we consider Sybase as the database of choice for developing the DAL.
I enclosed the source code in the form of a single file (“.vb” file). You can use it straight away or extend it further based on your needs. The entire discussion in this article will be based on version .NET 1.1.
If you are new to configuring Sybase for .NET or new to this series, I strongly suggest you refer to my first article of this series here.
Developing a separate class to hold all parameters of a Sybase stored procedure
In my previous two articles, you saw several methods for retrieving information from a Sybase database. In this article we shall focus on retrieving information using stored procedures available within Sybase database.
In the case of stored procedures, sometimes we may need to execute them by passing some parameters (related to the stored procedure itself). When we want to pass some parameter to a stored procedure, we need to know the parameter name, data type, size, and other details.
To hold all such information (sometimes called the parameter cache), I developed a separate class. The complete listing of the class is as follows:
This section explains the class listed in the previous section. Let us go through it part by part. First of all, consider the following:
<XmlRoot("SybaseProcParameter")> _ Public Class ASEProcParameter
The name of the class is “ASEProcPrameter” (user-defined). If we wanted to have this class serialized, the root of the XML would start at the “SybaseProcParameter” element. Even though for the above, serialization is not necessary, there are times when you want to pass the parameters between several tiers of your application. Then you need to serialize the information before you do marshaling or un-marshaling. In the above case, it would be automatically serialized to XML! Further proceeding, we have the following:
Public ParameterDirectionUsed As ParameterDirection
Those are all the class level variables needed to hold the parameter information of a stored procedure. I hope the name is reasonable and you can follow accordingly. Further proceeding, we have the following:
Public Sub New(ByVal passedParameterName As String, _
ByVal passedValue As Object, _
Optional ByVal passedSQLType As AseDbType = Nothing, _
Optional ByVal passedSize As Integer = Nothing, _
Optional ByVal passedDirection As ParameterDirection = ParameterDirection.Input)
ParameterName = passedParameterName
ParameterValue = passedValue
ParameterDataType = passedSQLType
ParameterSize = passedSize
ParameterDirectionUsed = passedDirection
End Sub
The above code fragment is a constructor which accepts certain information of a single parameter and passes the information to the class level variables. Further proceeding we have:
Public Function getASEParameter() As AseParameter
Dim returnSQLParameter As AseParameter = New AseParameter
We need to use the class defined in the previous sections when we want to add a parameter before executing a Sybase stored procedure. To help us in adding a parameter, I developed a new method as follows:
Public Sub SPaddParameter(ByVal ParameterName As String, Optional ByVal Value As Object = Nothing, Optional ByVal SQLType As SybaseDataType = Nothing, Optional ByVal Size As Integer = Nothing, Optional ByVal Direction As ParameterDirection = ParameterDirection.Input)
Dim buildDataType As AseDbType
Dim buildParameter As ASEProcParameter = Nothing
Select Case SQLType
Case SybaseDataType.SybaseString
buildDataType = AseDbType.VarChar
Case SybaseDataType.SybaseChar
buildDataType = AseDbType.Char
Case SybaseDataType.SybaseInteger
buildDataType = AseDbType.Integer
Case SybaseDataType.SybaseBit
buildDataType = AseDbType.Bit
Case SybaseDataType.SybaseDateTime
buildDataType = AseDbType.DateTime
Case SybaseDataType.SybaseDecimal
buildDataType = AseDbType.Decimal
Case SybaseDataType.SybaseMoney
buildDataType = AseDbType.Money
Case SybaseDataType.SybaseImage
buildDataType = AseDbType.Image
Case SybaseDataType.SybaseFloat
buildDataType = AseDbType.Double
End Select
buildParameter = New ASEProcParameter(ParameterName, Value, buildDataType, Size, Direction)
Dim dr As DataRow = dtParameterList.NewRow
'dr("ParamDetail") = buildParameter
Dim ser As XmlSerializer = New XmlSerializer(GetType (ASEProcParameter))
Dim sb As New StringBuilder
Dim writer As New StringWriter(sb)
ser.Serialize(writer, buildParameter)
writer.Close()
dr("ParamDetail") = writer.ToString
dtParameterList.Rows.Add(dr)
End Sub
The above method simply accepts a parameter name, value, data type, size, direction, and so on as parameters. To easily work with data types, I defined my own enumeration as follows:
Public Enum SybaseDataType
SybaseString
SybaseChar
SybaseInteger
SybaseBit
SybaseDateTime
SybaseDecimal
SybaseMoney
SybaseImage
SybaseFloat
End Enum
I will be mapping these data types to the original Sybase data types with the huge “select…case” (as in the previous code listing) within the above method itself. The whole cache of parameters (which are going to be passed to stored procedures) gets stored in “dtParameterList.”
To execute a Sybase stored procedure, we again need to work with all the objects, like connection, command, adapter and so on. The following is a complete code listing for executing a stored procedure (based on the parameter cache in the previous section) at the Sybase database, which in turn returns a data table:
Public Function SPgetDataTable(ByVal ProcName As String) As DataTable
Dim cmd As AseCommand
cmd = New AseCommand(ProcName, New AseConnection (_ConnectionString))
Dim Parm As AseParameter
Dim privateDataTable As New DataTable
With cmd
.CommandType = CommandType.StoredProcedure
DimUsedParameter As ASEProcParameter Dim ConvertedParameter As AseParameter
Dim drParam As DataRow
For Each drParam In dtParameterList.Rows
UsedParameter = Nothing
Dim ser As New XmlSerializer(GetType (ASEProcParameter))
Dim privateSQLDataAdapter As New AseDataAdapter (cmd)
privateSQLDataAdapter.Fill(privateDataTable)
.Connection.Close()
.Dispose()
privateSQLDataAdapter.Dispose()
End With
Return privateDataTable
End Function
I excluded some code for clarity (such as exception handling). You can get the complete program from the download (available from previous articles in this series). The explanation for the above code is available in the next section.
This section deals with the source code provided in the previous section. Let us go in a step by step manner. Let us first start with the following code:
Dim cmd As AseCommand
cmd = New AseCommand(ProcName, New AseConnection (_ConnectionString))
The above code fragment creates a new Sybase command to execute the stored procedure. I even created a database connection inline itself. Further proceeding we have the following:
Dim Parm As AseParameter
Dim privateDataTable As New DataTable
The above two lines are to work with the parameter cache and parameters of the stored procedure. Further proceeding we have:
With cmd
.CommandType = CommandType.StoredProcedure
DimUsedParameter As ASEProcParameter Dim ConvertedParameter As AseParameter
Dim drParam As DataRow
For Each drParam In dtParameterList.Rows
UsedParameter = Nothing
Dim ser As New XmlSerializer(GetType (ASEProcParameter))
From the above code fragment, I first mentioned that the command to execute at the Sybase database is a stored procedure. After that, I have a few declarations to work with the parameter cache. The loop is the heart of the method, which adds all the parameters available in the parameter cache to the command (which shall further proceed to the database and execute the stored procedure).
We convert each of our parameters in the parameter cache to the “AseParameter” type and finally add them to the command object. The command object executes the specified stored procedure by passing all those parameters added to it.
Dim privateSQLDataAdapter As New AseDataAdapter (cmd)
privateSQLDataAdapter.Fill(privateDataTable)
.Connection.Close()
.Dispose()
privateSQLDataAdapter.Dispose()
End With
Return privateDataTable
The above code fragment is where the real execution of the stored procedure takes place. We use a data adapter to work with the command, and to return the output in the form of data table. Once we have executed the stored procedure, we clear all the resources and finally return the data table to the calling program.
Summary
This ends our approach to designing a simple Data Access Layer. Even though it may not be helpful for enterprises, it would certainly be helpful for small to medium projects. Further, you can extend the class and create a service component (COM+) to support enterprises. You can have a look at one of my articles dealing with the enterprise level here to guide you to a better standard.
Any comments, suggestions, feedback, bugs, errors, enhancements are highly appreciated at jag_chat@yahoo.com