14.8.08

Clase para acceder a la base de datos Oracle desde .NET

Esta es una clase para ASP.NET, que trata de encapsular la conexión y las solicitudes a la base de datos Oracle, que es la que utilizo en mi trabajo.

Tiene todos los métodos necesarios para solicitar QUERYS comunes, o ejecutar complejos Procedimientos Almacenados, incluso con la posibilidad de recibir uno o más sys_refcursor como retorno.

El código:

' ------------------------------------------------------------------
' Clase   : DBConnector
' Autor   : Julio González
' Fecha   : 07/08/2007
' ------------------------------------------------------------------
Imports Microsoft.VisualBasic
Imports System.Data
Imports System.Data.OracleClient

Namespace JG

  ''' DBConnector
 '''
 ''' Conecta con una base de datos oracle utilizando
 ''' 
Public Class OraDBConnector
  '-----------------------
  ''' ParameterDef
    '''
  ''' Estructura para pasar los datos de los parámetros de los procedimientos.
  ''' Los miembros de esta estructura llevan los nombre y tipos que debe
  ''' recibir la clase Parameters de Oracle
  ''' </summary>
  ''' <remarks>#</remarks>
  Public Structure ParameterDef
     Public ParamName As String
     Public ParamType As OracleType
     Public ParamSize As Integer
     Public ParamDirection As ParameterDirection
     Public ParamValue As Object
  End Structure

  '-----------------------
  ''' <summary>
  ''' String de conección a la base de datos
  ''' </summary>
  ''' <remarks></remarks>
  Private _strConn As String
  ''' <summary>
  ''' Objeto Connection de Oracle
  ''' </summary>
  ''' <remarks></remarks>
  Private _conn As New OracleConnection
  ''' <summary>
  ''' Objeto Commander de Oracle que se utilirá para ejecutar procedimientos
  ''' y consultas
  ''' </summary>
  ''' <remarks></remarks>
  Private _Comm As New OracleCommand
  ''' <summary>
  ''' Objeto DataAdapter de Oracle para convertir las consultas en DataSet
  ''' </summary>
  ''' <remarks></remarks>
  Private _DataAdapder As New OracleDataAdapter

  '-----------------------
  ''' <summary>
  ''' Constructor de la clase
  ''' </summary>
  ''' <remarks></remarks>
  Public Sub New()
     Me._strConn = Nothing
  End Sub 'New

  '-----------------------
  ''' <summary>
  ''' Establece o retorna la cadena de conexión utilizada
  ''' </summary>
  ''' <strConn>Cadena de conexión</strConn>
  ''' <returns>Cadena de conexión</returns>
  ''' <remarks></remarks>
  Public Property dbConnectionString() As String
     Get
        Return _strConn
     End Get
     Set(ByVal strConn As String)
        _strConn = strConn
     End Set
  End Property  'dbConnectionString

  '-----------------------
  ''' <summary>
  ''' Método para abrir la conexión con la base de datos
  ''' </summary>
  ''' <remarks></remarks>
  Public Sub Open()
     If Me._strConn.Length = 0 Then
        Throw New System.Exception("DBConnector.dbConnect: No se estableció el conector")
        Exit Sub
     End If
     'trata de conectar
     Try
        Me._conn.ConnectionString = _strConn
        If Me._conn.State = ConnectionState.Open Then
           Me._conn.Close()
        End If
        Me._conn.Open()
     Catch ex As Exception
        Throw New System.Exception("DBConnector.dbConnect: " & ex.Message)
     End Try
  End Sub 'Open
  '-----------------------
  ''' <summary>
  ''' Método para obtener el objeto Connection establecido.
  ''' </summary>
  ''' <returns>Objeto conexión</returns>
  ''' <remarks></remarks>
  Public ReadOnly Property getConnection() As OracleConnection
     Get
        Return Me._conn
     End Get
  End Property 'getConnection

  '-----------------------
  ''' <summary>
  ''' Método para cerrar la conexión a la base de datos
  ''' </summary>
  ''' <remarks></remarks>
  Public Sub Close()
     Try
        If _conn.State = ConnectionState.Open Then
           _conn.Close()
           _conn = Nothing
        End If
     Catch ex As Exception
        'nada
     End Try
  End Sub 'Close
  'rellena un array list del usuario con parametros numericos
  Public Function AddParameter(ByVal Name As String, ByVal Value As Object, _
                                Optional ByVal Direction As ParameterDirection = _
                                ParameterDirection.Input) As ParameterDef
     Dim p As New ParameterDef
     With p
        .ParamName = Name
        .ParamType = OracleType.Number
        .ParamDirection = Direction
        .ParamValue = IIf(Value Is Nothing, DBNull.Value, Value)
     End With
     Return p
  End Function
  'rellena un array list del usuario con parametros string
  Public Function AddParameter(ByVal Name As String, ByVal Value As String, _
                                ByVal Size As Integer, _
                                Optional ByVal Direction As ParameterDirection = _
                                ParameterDirection.Input) As ParameterDef
     Dim p As New ParameterDef
     With p
        .ParamName = Name
        .ParamType = OracleType.VarChar
        .ParamDirection = Direction
        .ParamSize = Size
        .ParamValue = IIf(String.IsNullOrEmpty(Value), DBNull.Value, Value)
     End With
     Return p
  End Function
  'rellena un parametro para datos output por default
  Public Function AddParameter(ByVal Name As String, ByVal Type As OracleType) As ParameterDef
     Dim p As New ParameterDef
     With p
        .ParamName = Name
        .ParamType = Type
        .ParamDirection = ParameterDirection.Output
     End With
     Return p
  End Function
  Public Function AddParameter(ByVal Name As String, ByVal Type As OracleType, ByVal Size As Integer) _
  As ParameterDef
     Dim p As New ParameterDef
     With p
        .ParamName = Name
        .ParamType = Type
        .ParamSize = Size
        .ParamDirection = ParameterDirection.Output
     End With
     Return p
  End Function


  '-----------------------
  ''' <summary>
  ''' Ejecuta una sentencia SQL del tipo SELECT y retorna un objeto DataReader
  ''' </summary>
  ''' <param name="selectQuery">Sentencia SQL del tipo SELECT</param>
  ''' <returns>Objeto DataReader. En caso de error retorna NOTHING</returns>
  ''' <remarks></remarks>
  Public Function QueryToReaderData(ByVal selectQuery As String) As OracleDataReader
     Dim _Reader As OracleDataReader

     Try
        'valida el texto SQL
        Me.CheckSQLString(selectQuery)

        'valida el estado de la conexión
        Me.ValidateConnecton()

        Me._Comm = New OracleCommand(selectQuery, Me._conn)
        Me._Comm.CommandTimeout = 90
        _Reader = _Comm.ExecuteReader()
        Return _Reader
     Catch ex As Exception
        Throw New System.Exception("DBConnector.ReaderData: " _
                & ex.Message & " (" & selectQuery & ")")
        Return Nothing
     Finally
        Me._Comm = Nothing
     End Try
  End Function 'QueryToReaderData
  '-----------------------
  ''' <summary>
  ''' Ejecuta una sentencia SQL del tipo DELETE y retorna la cantidad de filas afectadas
  ''' </summary>
  ''' <param name="deleteQuery">Sentencia del tipo DELELE</param>
  ''' <returns>Un entero que representa la cantidad de filas afectadas.
  ''' En caso de error retorna NOTHING
  ''' </returns>
  ''' <remarks></remarks>
  Public Function Delete(ByVal deleteQuery As String) As Integer
     Try
        'controlo la sentencia
        Me.CheckSQLString(deleteQuery, "DELETE")

        'valida el estado de la conexión
        Me.ValidateConnecton()

        'ejecuto la consulta
        Dim recAfec As Integer
        recAfec = Me.ProcessExecuteNoQuery(deleteQuery)
        Return recAfec
     Catch ex As Exception
        Throw New System.Exception("DBConnector.Delete: " & ex.Message _
              & " (" & deleteQuery & ")")
        Return Nothing
     End Try
  End Function 'Delete
  '-----------------------
  ''' <summary>
  ''' Ejecuta una sentencia SQL del tipo DELETE y retorna la cantidad de filas afectadas
  ''' </summary>
  ''' <param name="insertQuery">Sentencia del tipo INSERT</param>
  ''' <returns>Un entero que representa la cantidad de filas afectadas.
  ''' En caso de error retorna NOTHING
  ''' </returns>
  ''' <remarks></remarks>
  Public Function Insert(ByVal insertQuery As String) As Integer
     Try
        'valido el texto SQL
        Me.CheckSQLString(insertQuery, "INSERT")

        'valido la conexión
        Me.ValidateConnecton()

        Dim recAfec As Integer
        recAfec = Me.ProcessExecuteNoQuery(insertQuery)
        Return recAfec
     Catch ex As Exception
        Throw New System.Exception("DBConnector.Insert: " & ex.Message)
        Return Nothing
     End Try
  End Function 'Insert
  '-----------------------
  ''' <summary>
  ''' Procedimiento privado para atender a los procedimientos públicos
  ''' DELETE e INSERT
  ''' </summary>
  ''' <param name="strSQL">Sentencia SQL a ejecutar</param>
  ''' <returns>Cantidad de filas afectadas</returns>
  ''' <remarks></remarks>
  Private Function ProcessExecuteNoQuery(ByVal strSQL As String) As Integer
     Try
        'valida el estado de la conexión
        ValidateConnecton()

        Dim recAfec As Integer
        Me._Comm = New OracleCommand(strSQL, _conn)
        Me._Comm.CommandTimeout = 90
        recAfec = Me._Comm.ExecuteNonQuery()
        Return recAfec
     Catch ex As Exception
        Throw New System.Exception(ex.Message & " (" & strSQL & ")")
        Return Nothing
     Finally
        Me._Comm = Nothing
     End Try
  End Function
  '-----------------------
  ''' <summary>
  ''' Ejecuta un query y retorna la primera columna de la primera fila
  ''' </summary>
  ''' <param name="selectQuery">Sentencia SQL a ejecutar</param>
  ''' <returns>Valor de la primera columna de la primera fila</returns>
  ''' <remarks></remarks>
  Public Function ExecScalar(ByVal selectQuery As String) As String
     Try
        'controlo la sentencia
        Me.CheckSQLString(selectQuery)

        'valida el estado de la conexión
        Me.ValidateConnecton()

        Me._Comm = New OracleCommand(selectQuery, _conn)
        Me._Comm.CommandTimeout = 90
        Dim strResult As String
        strResult = Me._Comm.ExecuteScalar().ToString()
        Return strResult

     Catch ex As Exception
        Throw New System.Exception("DBConnector.ExecScalar: " _
                  & ex.Message & " (" & selectQuery & ")")
        Return Nothing
     Finally
        _Comm = Nothing
     End Try
  End Function  'ExecScalar
  '-----------------------
  ''' <summary>
  ''' Ejecuta una sentencia del tipo SELECT y retorna un objeto DataTable
  ''' </summary>
  ''' <param name="selectQuery">Sentencia SQL a ejecutar</param>
  ''' <returns>Objeto DataTable con el resultado de la consulta</returns>
  ''' <remarks></remarks>
  Public Function QueryToDataTable(ByVal selectQuery As String) As DataTable
     Try
        'valida el texto SQL
        Me.CheckSQLString(selectQuery)

        'valida el estado de la conexión
        ValidateConnecton()

        Me._Comm = New OracleCommand(selectQuery, Me._conn)
        Dim myDataTable As New DataTable
        Me._DataAdapder = New OracleDataAdapter(Me._Comm)
        Me._Comm.CommandTimeout = 300
        Me._Comm.CommandType = CommandType.Text
        Me._DataAdapder.Fill(myDataTable)

        Return myDataTable
     Catch ex As Exception
        Throw New System.Exception("DBConnector.FillDataTable: " _
                        & ex.Message & " (" & selectQuery & ")")
        Return Nothing
     Finally
        Me._Comm = Nothing
     End Try
  End Function  'QueryToDataTable
  '-----------------------
  ''' <summary>
  ''' Ejecuta una sentencia del tipo SELECT y retorna un objeto DataSet
  ''' </summary>
  ''' <param name="selectQuery">Sentencia SQL a ejecutar</param>
  ''' <returns>Objeto DataSet con el resultado de la consulta</returns>
  ''' <remarks></remarks>
  Public Function QueryToDataSet(ByVal selectQuery As String, _
               Optional ByVal srcTable As String = "myTable") As DataSet
     Try
        'valida el texto SQL
        Me.CheckSQLString(selectQuery)

        'valida el estado de la conexión
        Me.ValidateConnecton()

        Me._Comm = New OracleCommand(selectQuery, Me._conn)
        Dim MyDataSet As New DataSet
        Me._DataAdapder = New OracleDataAdapter(Me._Comm)
        Me._Comm.CommandTimeout = 300
        Me._Comm.CommandType = CommandType.Text
        Me._DataAdapder.Fill(MyDataSet, srcTable)
        Return MyDataSet
     Catch ex As Exception
        Throw New System.Exception("DBConnector.FillDataSet: " _
                    & ex.Message & " (" & selectQuery & ")")
        Return Nothing
     Finally
        Me._Comm = Nothing
     End Try
  End Function  'QueryToDataSet
  '-----------------------
  ''' <summary>
  ''' Genera acumulacion de tablas en un mismo DataSet que el usuario debe pasar
  ''' como parámetro
  ''' </summary>
  ''' <param name="selectQuery">Sentencia SQL a ejecutar</param>
  ''' <param name="srcTable">Nombre de la tabla</param>
  ''' <param name="myDataSet">Objeto DataSet del usuario</param>
  ''' <returns>Objeto DataSet con el resultado de la consulta</returns>
  ''' <remarks></remarks>
  Public Function QueryToDataSet(ByVal selectQuery As String, _
                        ByVal srcTable As String, _
                        ByVal myDataSet As DataSet) As DataSet
     Try
        'valida el texto SQL
        Me.CheckSQLString(selectQuery)

        'valida el estado de la conexión
        Me.ValidateConnecton()

        Me._Comm = New OracleCommand(selectQuery, _conn)
        Me._DataAdapder = New OracleDataAdapter(_Comm)
        Me._Comm.CommandTimeout = 300
        Me._Comm.CommandType = CommandType.Text
        Me._DataAdapder.Fill(myDataSet, srcTable)
     Catch ex As Exception
        Throw New System.Exception("DBConnector.FillDataSet (vs): " _
                    & ex.Message & " (" & selectQuery & ")")
     Finally
        Me._Comm = Nothing
     End Try

     Return myDataSet
  End Function  'QueryToDataSet
  '-----------------------
  ''' <summary>
  ''' Ejecuta un procedimiento almacenado
  ''' </summary>
  ''' <param name="CommandText">Texto de invocación al procedimiento almacenado</param>
  ''' <param name="Parameters">
  ''' Objeto ArrayList conteniendo un objeto JG.OraDbConnector.ParameterDef
  ''' por cada parámetro que debe recibir el procedimiento almacenado.
  ''' </param>
  ''' <param name="keyReader">
  ''' Opcional: Clave de acceso al objeto DataReader
  ''' </param>
  ''' <returns>
  ''' Retorna un ojeto HashTable con el resultado de la ejecución.
  ''' Si el procedimiento almacenado tiene uno o más parámetros OUTPUT del tipo 
  ''' REF CURSOR, el objeto HashTable retornado contiene un elemento cuya clave es
  ''' _DR conteniendo un objeto OracleDataReader con todos los cursores.
  ''' El resto de los elementos del objeto retornado son los parámetros de tipo
  ''' IN OUT o OUT (excepto los ref cursor). La clave de acceso a cada uno
  ''' de los elementos del HashTable es el nombre definido en ParamName.
  ''' </returns>
  ''' <remarks>
  ''' El objeto OracleDataReader contiene los REF CURSOR en el mismo orden en que se
  ''' pasaron los parametros de tipo OracleType.Cursor
  ''' </remarks>
  Public Function ExecuteStoredProcedure(ByVal CommandText As String, _
                      Optional ByVal Parameters As ArrayList = Nothing, _
                      Optional ByVal keyReader As String = "_DR") As Hashtable
     Dim _parameters As ArrayList = Parameters
     Dim _retVal As New Hashtable
     Dim _Reader As OracleDataReader

     Me._Comm = New OracleCommand()
     With Me._Comm
        .CommandText = CommandText
        .CommandType = CommandType.StoredProcedure
        .Connection = Me._conn
     End With
     Dim j As New StringBuilder
     Dim i As Integer
     'ejecuto el procedimiento
     Try
        'agrego los parámetros
        Me.AddParameters(_parameters)
        With Me._Comm.Parameters
           For i = 0 To .Count - 1
              j.Append(.Item(i).ParameterName & ": " & .Item(i).Value & " (" & .Item(i).Direction & ")" & " // ")

           Next i
        End With

        _Reader = Me._Comm.ExecuteReader
        _retVal.Add(keyReader, _Reader)  'agrego los refcursor a la tabla
     Catch ex As Exception
        Throw New System.Exception("DBConnector.ExecuteStoredProcedure: " _
                & ex.Message & " (" & CommandText & ") " & j.ToString)
        Me._Comm = Nothing
        Return Nothing
     End Try
     'asigno los parámetros

     Try
        If _parameters.Count > 0 Then
           For Each param As ParameterDef In _parameters
              With param
                 If .ParamDirection = ParameterDirection.InputOutput Or _
                    .ParamDirection = ParameterDirection.Output Then
                    If .ParamType <> OracleType.Cursor Then
                       _retVal.Add(.ParamName, Me._Comm.Parameters.Item(.ParamName).Value)
                    End If
                 End If
              End With
           Next

        End If
     Catch ex As Exception
        Throw New System.Exception("DBConnector.ExecuteStoredProcedure: " & ex.Message)
     End Try

     Return _retVal
  End Function  'ExecuteStoredProcedure
  '-----------------------
  ''' <summary>
  ''' Ejecuta una función almacenado
  ''' </summary>
  ''' <param name="CommandText">Texto de invocación al procedimiento almacenado</param>
  ''' <param name="Parameters">
  ''' Objeto ArrayList conteniendo un objeto JG.OraDbConnector.ParameterDef
  ''' por cada parámetro que debe recibir el procedimiento almacenado.
  ''' </param>
  ''' <returns>
  ''' Retorna un ojeto HashTable con el resultado de la ejecución.
  ''' Si el procedimiento almacenado tiene uno o más parámetros OUTPUT del tipo 
  ''' REF CURSOR, el objeto HashTable retornado contiene un elemento cuya clave es
  ''' _DR conteniendo un objeto OracleDataReader con todos los cursores.
  ''' El resto de los elementos del objeto retornado son los parámetros de tipo
  ''' IN OUT o OUT (excepto los ref cursor). La clave de acceso a cada uno
  ''' de los elementos del HashTable es el nombre definido en ParamName.
  ''' </returns>
  ''' <remarks>
  ''' El objeto OracleDataReader contiene los REF CURSOR en el mismo orden en que se
  ''' pasaron los parametros de tipo OracleType.Cursor
  ''' </remarks>
  Public Function ExecuteStoredFunction(ByVal CommandText As String, _
                  ByVal Parameters As ArrayList) As Hashtable
     Dim __nomObj As String = "DBConnector.ExecuteStoredFunction: "
     Dim _parameters As ArrayList = Parameters
     Dim _retVal As New Hashtable
     Dim _Reader As OracleDataReader
     Dim outParams As Integer = 0

     'verifico cuantos parámetros return_value hay
     For Each param As ParameterDef In _parameters
        With param
           If .ParamDirection = ParameterDirection.ReturnValue Then
              outParams = outParams + 1
           End If
        End With
     Next
     'controlo que sólo se pase un parámetro return_value
     If outParams = 0 Then
        Throw New System.Exception(__nomObj & "No se incluyó el parámetro RETURN_VALUE.")
        Return Nothing
     End If
     If outParams > 1 Then
        Throw New System.Exception(__nomObj & "Se incluyó más de un parámetro RETURN_VALUE.")
        Return Nothing
     End If

     'ejecuto el procedimiento
     Try
        'parámetros del comando
        _Comm = New OracleCommand()
        With _Comm
           .CommandText = CommandText
           .CommandType = CommandType.StoredProcedure
           .Connection = _conn
        End With

        'agrego los parámetros de la función
        AddParameters(_parameters)
        _Reader = _Comm.ExecuteReader()
        _retVal.Add("_DR", _Reader)  'agrego los refcursor a la tabla
     Catch ex As Exception
        Throw New System.Exception(__nomObj & ex.Message & " (" & CommandText & ")")
        _Comm = Nothing
        Return Nothing
     End Try
     'asigno el valor de retorno
     For Each param As ParameterDef In _parameters
        With param
           If .ParamDirection = ParameterDirection.Input Or _
              .ParamDirection = ParameterDirection.Output Or _
              .ParamDirection = ParameterDirection.ReturnValue Then
              If .ParamType <> OracleType.Cursor Then
                 _retVal.Add(.ParamName, _Comm.Parameters.Item(.ParamName).Value)
              End If
           End If
        End With
     Next
     Return _retVal
  End Function  'ExecuteStoredFunction
  '-----------------------
  ''' <summary>
  ''' Asigna los parametros a un objeto OracleCommander
  ''' </summary>
  ''' <param name="Parameters">
  ''' Objeto ArrayList que contiene los parámetros a asignar al
  ''' objeto OracleCommand
  ''' </param>
  ''' <remarks></remarks>
  Private Sub AddParameters(ByVal Parameters As ArrayList)
     If Parameters Is Nothing Then Exit Sub
     If Parameters.Count = 0 Then Exit Sub

     For Each param As ParameterDef In Parameters
        With param
           If .ParamType = OracleType.Cursor And .ParamDirection <> ParameterDirection.Output Then
              Throw New System.Exception("(AddParameters): Se ha definido un tipo de parámetro " _
                  & "CURSOR cuya dirección no es OUT (" & .ParamName & ")")
              Exit Sub
           End If
           Me._Comm.Parameters.Add(.ParamName, .ParamType)
           If .ParamSize <> Nothing Then
              Me._Comm.Parameters.Item(.ParamName).Size = .ParamSize
           End If
           If .ParamValue IsNot Nothing Then
              Me._Comm.Parameters.Item(.ParamName).Value = .ParamValue
           End If
           If .ParamDirection <> Nothing Then
              Me._Comm.Parameters.Item(.ParamName).Direction = .ParamDirection
           End If
        End With
     Next
  End Sub
  '-----------------------
  ''' <summary>
  ''' Controla si la conexión esta activa
  ''' </summary>
  ''' <remarks>
  ''' Esta función previene de cortes de conexión.
  ''' </remarks>
  Private Sub ValidateConnecton()
     If Me._conn Is Nothing Then
        Throw New System.Exception("No se estableció la conexión con la base de datos.")
        Exit Sub
     End If
     If Me._conn.State = ConnectionState.Broken Then
        Throw New System.Exception("Se ha perdido la conexión con la base de datos.")
        Exit Sub
     End If
     If Me._conn.State = ConnectionState.Closed Then
        Throw New System.Exception("La conexión con la base de datos está cerrada.")
        Exit Sub
     End If
     If Me._conn.State = ConnectionState.Connecting Or _
        Me._conn.State = ConnectionState.Executing Or _
        Me._conn.State = ConnectionState.Fetching Then
        Throw New System.Exception("La conexión a la base de datos está ocupada.")
        Exit Sub
     End If
  End Sub
  '-----------------------
  ''' <summary>
  ''' Corrobora si la sentencia SQL es del tipo esperado.
  ''' </summary>
  ''' <param name="sqlString">Sentencia SQL a controlar</param>
  ''' <param name="typeSQL">
  ''' Opcional. Tipo de sentencia esperado. Por omisión: SELECT.
  ''' </param>
  ''' <returns>La sentencia SQL enviada sin espacios en blanco irrelevantes</returns>
  ''' <remarks></remarks>
  Private Function CheckSQLString(ByVal sqlString As String, _
                   Optional ByVal typeSQL As String = "SELECT") As String
     'verifico que venga el dato y que sea un SQL DELETE
     sqlString = Trim(sqlString)
     If sqlString.Length = 0 Then
        Throw New System.Exception("La sentencia SQL está vacía.")
        Return sqlString
     End If
     If Not UCase(sqlString).StartsWith(typeSQL) Then
        Throw New System.Exception("La sentencia SQL no es del tipo esperado.")
        Return sqlString
     End If
     Return sqlString
  End Function
  '-----------------------
  ''' <summary>
  ''' Previene el no cierre de la base de datos al morir el objeto conxión
  ''' </summary>
  ''' <remarks></remarks>
  Protected Overrides Sub Finalize()
     Me.Close()
     MyBase.Finalize()
  End Sub 'Finalize

  '-----------------------
  ''' <summary>
  ''' Convierte un DataReader en un DataSet
  ''' </summary>
  ''' <remarks></remarks>
  Public Function ConvertDataReaderToDataSet(ByVal reader As OracleDataReader) As DataSet
     Dim dataSet As DataSet = New DataSet()
     Dim schemaTable As DataTable = reader.GetSchemaTable()
     Dim dataTable As DataTable = New DataTable()
     Dim intCounter As Integer

     For intCounter = 0 To schemaTable.Rows.Count - 1
        Dim dataRow As DataRow = schemaTable.Rows(intCounter)
        Dim columnName As String = CType(dataRow("ColumnName"), String)
        Dim column As DataColumn = New DataColumn(columnName, _
                                CType(dataRow("DataType"), Type))
        dataTable.Columns.Add(column)
     Next

     dataSet.Tables.Add(dataTable)
     While reader.Read()
        Dim dataRow As DataRow = dataTable.NewRow()
        For intCounter = 0 To reader.FieldCount - 1
           dataRow(intCounter) = reader.GetValue(intCounter)
        Next
        dataTable.Rows.Add(dataRow)
     End While

     Return dataSet
  End Function
End Class  'DBConnector
End Namespace

Ejemplos:

Este ejemplo muestra como ejecutar una consulta simple. Se trata de una página que tiene un TEXTAREA, donde el usuario escribe o pega una consulta, la que es ejecutada por la clase que conecta con la base.


Imports JG
Imports System.Data
Imports System.Threading
Imports System.Globalization

Partial Class _Default
Inherits System.Web.UI.Page

    'ejecuta una sentencia sql capturade del input SQLScript de la pagina.
Protected Sub EjecutaCodigo()
  Dim Sql As String = SQLScript.Value
  Dim conn As New OraDBConnector()
  Dim table As DataTable
  'ServidorDestino es un combo que tiene como Value, la clave de cadena de conexion
  Dim destConn As String = Me.ServidorDestino.SelectedItem.Value

  Try
     'rescata la cadena de conexion desde el archivo web.config
     conn.dbConnectionString = ConfigurationManager.AppSettings.Item(destConn).ToString()
     conn.Open()
  Catch ex As Exception
     Me.lblError.Text = ex.Message.ToString()
     Exit Sub
  End Try
  Try
     'ejecuta la sentencia sql, que es devuelta en un DataTable
     table = conn.QueryToDataTable(Sql)
  Catch ex As Exception
     Me.lblError.Text = ex.Message.ToString()
     Exit Sub
  Finally
     conn.Close()
  End Try
  If table.Rows.Count = 0 Then
     Me.lblError.Text = "No hay filas para la consulta dada."
     Exit Sub
  End If
  'agrega el data table a un GridView
  With Me.gvDatos
     .DataSource = table
     .DataBind()
  End With
  btCSV.Visible = True
End Sub

End Class

Este ejemplo muestra como ejecutar un procedimiento almacena en la base que, en este caso, retorna un sys_refcursor.

>
'----------------------------------------
'rellena un combo con usuarios
Private Sub RellenarComboUsuarios()
  Dim conn As OraDBConnector

  'apertura de la conexion
  Try
     conn = AbrirConexionBD()
  Catch ex As Exception
     Throw New System.Exception(ex.Message)
     Exit Sub
  End Try

  'parametros del paquete
  Dim arr As New ArrayList
  arr.Add(conn.AddParameter("pv_mca_habilitados", "S", 1))
  arr.Add(conn.AddParameter("rv_cursor", OracleType.Cursor))

  'ejecuta el procedimiento
  Dim htProc As Hashtable
  htProc = conn.ExecuteStoredProcedure( _
           "pk_net_art_traslados_admin.User_Enum_Usuarios", arr)

  Dim ODR As OracleDataReader
  ODR = htProc("_DR") 'obtengo el OracleDataReader con el cursor
  If Not ODR.HasRows Then
     conn.Close()
     Exit Sub
  End If

  'asigno las filas al combo
  Dim ds As DataSet
  ds = conn.ConvertDataReaderToDataSet(ODR)
  conn.Close()
  With ddlUsuarios
     .DataSource = ds
     .DataTextField = "nombre"
     .DataValueField = "cod_user"
     .DataBind()
     .Items.Insert(0, New ListItem("Seleccione", 0))
  End With
  ddlUsuarios.SelectedIndex = 5
End Sub 'RellenarComboUsuarios

Este ejemplo es similar al anterior, pero muestra otra forma de informar los parámetros del procedimiento almacenado.


'lee los menues por perfil
Private Sub BuscarMenuesPorPerfil(ByVal perfil As Integer)
  Dim conn As New OraDBConnector()
  Dim sContext As New SiteContext(Request.Url.Host)
  Dim connStr As String
  Dim usr As String = User.Identity.Name

  'apertura de la conexion
  Try
     connStr = sContext.GetDBConnectionString()
     conn.dbConnectionString = connStr
     conn.Open()
  Catch ex As Exception
     Throw New System.Exception("BuscarMenuesPorPerfil: " & ex.Message)
     Exit Sub
  End Try

  'busco los datos del usuario
  Dim param As New OraDBConnector.ParameterDef
  Dim arr As New ArrayList

  'codigo del perfil
  With param
     .ParamName = "pv_cod_perfil"
     .ParamSize = 10
     .ParamType = OracleType.Number
     .ParamValue = perfil
  End With
  arr.Add(param)
  'cursor que retorna el paquete
  With param
     .ParamName = "rv_cursor"
     .ParamType = OracleType.Cursor
     .ParamDirection = Data.ParameterDirection.Output
     .ParamValue = Nothing
  End With
  arr.Add(param)

  'ejecuta el procedimiento
  Dim htProc As Hashtable
  htProc = conn.ExecuteStoredProcedure("pk_net_art_traslados_menu.Menues_Por_Perfil_Admin", arr)

  Dim ODR As OracleDataReader
  ODR = htProc("_DR") 'obtengo el OracleDataReader con el cursor

  'relleno el campo oculto ds_hide
  Dim ds As DataSet
  ds = conn.ConvertDataReaderToDataSet(ODR)
  conn.Close()
  'muestro el treeview
  RellenaTreeView1(ds)
End Sub

El archivo con el código puede ser bajado desde aquí.

1 Comentario:

Mau dice...

Que tal, te recomiendo mucho más ocupar la nueva librería de Oracle para .NET:
Oracle.DataAccess

Es bastante más potente y se integra mucho mejor con los tipos de datos nativos de PL/SQL.

Saludos!