Está en la página 1de 12

1

ADO.NET
La programacin de BD en .NET utiliza unas cuantas clases en System.Data y sus espacios de nombres
hijos, lo que en conjunto se conoce como ADO.NET. Estas clases y sus mtodos permiten recuperar
datos a partir de Microsoft SQL Server o una de las fuentes de datos OLE DB ms genrica, procesarlos
y actualizar las tablas de la base de datos original.
Un proveedor de datos funciona como un puente entre una aplicacin y la fuente de datos.
Los proveedores de datos permiten que una aplicacin lea y escriba los datos almacenados en una
fuente de datos. En la actualidad ADO.NET soporta tres proveedores:
OLE DB .NET. Permite acceder a una fuente de datos para la que exista un proveedor OLE DB,
aunque necesita un conmutador para administrar cdigo no administrado.
Es compatible con los siguientes proveedores OLE DB:
- SQLOLEDB (para SQL Server)
- MSDAORA (para Oracle)
- Microsoft.Jet.OLEDB.4.0 (para Access)
SQL Server .NET. Permite acceder a una fuente de datos SQL Server 7.0 o versiones posteriores.
ODBC .NET. Funciona como un puente a una fuente ODBC. Actualmente slo soporta
controladores ODBC de: Access, SQL Server y Oracle

El modelo de objetos ADO.NET


Los objetos que componen la arquitectura se han dividido en dos grupos:
- Los objetos que estn incluidos en el Proveedor de datos .NET
- Y los que pertenecen a la arquitectura desconectada de ADO.NET

Proveedor de datos .Net


Connection

DataAdapter

(Datos sin conexin)


DataSet

Command
Parameter

DataReader

Connection. Su funcin es establecer una conexin con la fuente de datos.


Dispone, entre otros, de:
Propiedades:
ConnectinString. Cadena de caracteres con el nombre de la base de datos.
Mtodos:
Open. Permite abrir la conexin
Close. Permite cerrar la conexin.

2
Command. Permite realizar una consulta a la base de datos, enviarle un comando (orden SQL) o
invocar alguno de los procedimientos almacenados.
Para ello, entre otros, dispone de distintos mtodos Execute:
ExecuteNonQuery. Ejecuta la consulta de accin y devuelve el nmero de filas afectadas.
(Ej: INSET, UPDATE o DELETE SQL)
ExecuteReader. Ejecuta la consulta de seleccin, y devuelve el objeto DataReader que permite
acceder al resulset (Conjunto de filas y columnas).
(Ej: SELECT ...)
ExecuteEscalar. Ejecuta la consulta de seleccin y devuelve un valor escalar.
Propiedades que permiten crear el comando:
CommandText. Cadena con la sentencia SQL de la consulta.
Connection. Objeto Connection asociado al comando.
DataReader. Es el objeto que devuelve el mtodo ExecuteReader. Representa un resulset de avance, de
slo lectura.
Un resulset es el conjunto de filas y columnas obtenidas por la ejecucin de un comando de seleccin.
DataReader dispone del mtodo Read que permite obtener una nueva fila de resultados, la fila actual.
Una vez obtenida la fila se pueden realizar consultas a cada campo utilizando la propiedad Item, el
mtodo GetValue, o los mtodos Getxxxx con declaracin de tipos (GetString, GetInt32, ...)
Propiedades:
Item(i). Slo lectura. Permite acceder a cualquier campo, por su nombre o por el ndice de su
columna (comienza por 0).
FieldCount. Obtiene el N de campos.
Mtodos:
Read. Pasa a la fila siguiente y devuelve True si hay ms filas y False si ha llegado al final del
resulset. Es decir, obtiene una nueva fila de resultados.
Close. Cierrar el objeto.
GetName(i). Recupera el valor del campo de ndice i, de la fila actual.
GetValue(i). Obtiene el valor de un campo (en su formato nativo).
DataSet. Es el objeto que contiene una copia local de los datos ledos de una o varias fuentes de datos.
Su objetivo es guardar y procesar los datos. Se puede considerar como una base de datos relacional
disminuida, en memoria.
Est completamente desconectado de la fuente de datos, tanto fsica como lgicamente. Por ejemplo, se
puede rellenar un DataSet con uno o varios resulset procedentes de sentencias SQL sobre distintas bases
de datos, incluso de distintos proveedores; se puede rellenar un DataSet con una base de datos, o
incluso se puede rellenar con una tabla de datos que se haya creado por cdigo.
Una vez cargados los datos en el objeto DataSet, se puede:
- Crear relaciones entre los diferentes resulset.
- Navegar por los resulset
La independencia de la fuente de datos especfica se consigue gracias al objeto DataAdapter. Este es el
objeto que carga los datos en el DataSet y es capaz de actualizar una fuente de datos con los datos que
la aplicacin ha agregado, eliminado o modificado.
DataAdapter. Funciona como un puente entre los objetos Connection y DataSet. Puede recuperar y
actualizar datos de un origen a travs de sus mtodos Fill y Update.
Fill. Copia los datos del origen de datos al DataSet.
Update. Mueve los datos del DataSet a la base de datos.
Actualiza la BD, aade, elimina o actualiza sus filas.

Espacios de nombres
Los diferentes proveedores utilizan diferentes espacios de nombres y tambin utilizan diferentes
nombres para los objetos.
Para utilizar en las aplicaciones estos espacios de nombres se deben importar. Por lo tanto se utilizar
alguna de las siguientes sentencias dependiendo del proveedor de datos que se desee utilizar:
Imports SystemData. Contiene los objetos DataSet y sus derivados: DataTable, DataRow,
DataRelation
Imports System.Data.SqlClient. Contiene objetos del proveedor SQL Server .Net: SqlConnection,
SqlCommand, SqlDataReader y SqlDataAdapter
Imports.System.OleDb. Contiene objetos del proveedor OLE DB .NET: OleDbConecction,
OleDbCommand, OleDbDataReader y OleDbDataAdapter
Nosotros utilizaremos OLE DB. Se describen los objetos con sus miembros para este proveedor.

El Objeto Connection
Tanto si se trabaja en modo conectado como sin conexin, lo primero que se debe hacer con una fuente
de datos es abrir una conexin en ella. Esto implica que se crea un objeto Connection que conecta con
la base de datos especificada.
Relacin incompleta de miembros soportados por OLE DB.
Propiedades:
ConnectinString. Cadena utilizada para conectar con la fuente de datos.
ConectionTimeout. Nmero de segundos despus del cual una conexin fallida se interrumpe. Es de
slo lectura, ya que este valor se configura en la propiedad ConnectionString. El valor
predeterminado es de 15 segundos.
DataBase. Devuelve el nombre de la base de datos especificada en la propiedad ConnectionString. Slo
lectura.
DataSource. Devuelve el nombre del atributo Data Source, especificado en ConnectionString. Slo
lectura.
Provider. Devuelve el valor del atributo Provider (proveedor) especificado en ConnectionString. Slo
lectura.
ServerVersion. Devuelve la versin del servidor conectado en formato xx.yy.zzzz o una cadena vaca si
no puede obtener esta informacin
State. Devuelve es estado actual de la conexin. Es un campo de bit codificado. Puede ser un valor de
la enumeracin ConnectionState (Closed, Open, ...)
Mtodos:
Open. Abre la conexin.
Close. Cierrra la conexin y libera todas las fuentes de datos asociadas.
BeginTransation. Comienza una transaccin de base de datos utilizando el nivel de aislamientos
especificado en el argumento opcional.
ChangeDataBase. Cambia el nombre de la base de datos para la conexin actual
CreateCommand. Crea un objeto Command asociado a la conexin actual.
Sucesos:
StateChange. Se activa cuando la propiedad State cambia.

4
Propiedad ConnectionString . Cadena de caracteres que define el tipo de la BD a la que est conectado
(Proveedor), su ubicacin, su nombre y otros atributos separados por ;
Atributos:
Provider. Especifica el nombre del proveedor OLE DB utilizado:
- SQLOLEDB (para SQL Server)
- MSDAORA (para Oracle)
- Microsoft.Jet.OLEDB.4.0 (para Access)
Data Source. Especifica dnde est la base de datos. Puede ser:
- La ruta y nombre de una base de datos Access.
- El nombre de la mquina en la que est la base de datos Oracle o SQL Server.
User ID. Nombre del usuario de una cuenta vlida para la BD.
Password. Contrasea de esa cuenta.

Procedimientos de apertura de una conexin a una base de datos.

La apertura de la conexin es imprescindible tanto en modo desconectado como conectado


1. Crear una instancia del objeto Connection.
2. Establecer la cadena de conexin.
3. Abrir la conexin.
1. Crear una instancia del objeto Connection.
Este objeto puede devolver eventos o no.
Dim Cn As New OleDbConnection

-o-

Dim WithEvents Cn As New OleDbConnection

2. Establecer la cadena de conexin.

El atributo Data Source de la cadena de conexin contiene el nombre de la BD con su ruta de


acceso. Si la BD se encuentra en el mismo directorio que el archivo .exe del proyecto, no es
necesario escribir la ruta.
En este caso Biblio.mdb se encuentra en el subdirectorio bin\Debug del proyecto
Dim CadenaConexion As String
CadenaConexion = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Biblio.mdb;"
Cn.ConnectionString = CadenaConexion

Los pasos 1 y 2 se pueden agrupar:


Dim CadenaConexion As String
CadenaConexion = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Biblio.mdb;"
Dim Cn = New OleDbConnection(CadenaConexion)

3. Abrir la conexin.
Cn.Open()

Al abrir la conexin conviene comprobar su estado y controlar los errores.


Dim cadena As String
Try
Cn.Open()
cadena = Cn.State.ToString
Me.TxtConexion.Text = cadena
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try

Procedimientos de Cierre de una conexin.


If Cn.State = ConnectionState.Open Then Cn.Close()

El mtodo Close no da error si la conexin estaba cerrada.


Cn.Close()

El Objeto Command
Una vez abierta una conexin se puede elegir entre trabajar en modo conectado o desconectado.
En modo conectado, lo normal es crear un objeto Command que contenga una consulta a una base de
datos y a continuacin ejecutar el mtodo Executexxxx que corresponda con el tipo de consulta:
De seleccin para obtener datos de la BD
De accin para actualizar datos en la BD
Propiedades:
Connection. Obtiene o establece el objeto Connection de este comando.
CommandText. String. Obtiene o establece la instruccin SQL, nombre de la tabla o

procedimiento almacenado, que se va a ejecutar en el origen de datos.


CommandType. Obtiene o establece un valor que indica el tipo de consulta. Es decir, cmo se
interpreta la propiedad CommandText. Sus valores pueden ser:
Text. Sentencia SQL (por defecto)

StoredProcedure. Procedimiento almacenado


TableDirec. Tabla
CommandTimeout. Integer. Obtiene o establece el tiempo de espera hasta que se interrumpa el

intento de ejecutar un comando y se genere un error.


Parameters. Coleccin de parmetros del comando.
Transaction. Obtiene o establece el objeto Transaction correspondiente a la transaccin en la que se
ejecuta este comando.
UpdateRowSource. Obtiene o establece la manera en que se aplican los resultados del comando

a DataRow cuando lo utiliza el mtodo Update del DataAdapter. (Slo en


desconectado)
Mtodos:
Cancel. Cancela la ejecucin del comando.
ResetCommandTimeout. Restablece el valor predeterminado de la propiedad CommandTimeout (30
segundos).
Para lectura de datos:
ExecuteNonQuery. Ejecuta la consulta de accin y devuelve el nmero de filas afectadas.
ExecuteReader. Ejecuta una consulta de seleccin y devuelve un objeto DataReader que permite
acceder al resulset (Conjunto de filas y columnas obtenidos por la consulta).

Este mtodo puede incluir un valor opcional CommandBehavior.


CommandBehavior es una enumeracin que proporciona una descripcin de los resultados de
la consulta y de sus efectos en la base de datos.
Se puede utilizar una combinacin bit a bit de sus valores. Por ejemplo si se devuelve una nica
fila o si se debe cerrar la conexin cuando finalice el mtodo, etc.
ExecuteScalar. Ejecuta la consulta y devuelve un valor escalar. Es decir, devuelve la primera

columna de la primera fila del conjunto de resultados devuelto por la consulta.


Funciona con cualquier consulta SQL y devuelve el primer campo de la primera
fila.
Para consultas parametrizadas:
CreateParameter. Crea un objeto Parameter conectado a este comando parametrizado.

6
Procedimientos de creacin y ejecucin de comandos
El procedimiento general es el siguiente:
1. Abrir la conexin
2. Crear y ejecutar el comando
3. Cerrar la conexin
Crear el comando:
1. Crear una instancia del objeto Command
Dim Cmd As New OleDbCommand

2. Establecer, al menos, las propiedades CommandText y Connection


Por defecto se va a interpretar que CommandText contiene una sentencia SQL, si no es as
tambin hay que establecer CommandType con el valor correspondiente.
Dim Sql As String
Sql = "Select ..." "Insert ..." "Update... " "Delete ..."
With Cmd
.CommandText = Sql
.Connection = Cn
End With

Los pasos 1 y 2 se pueden agrupar:


Dim Sql As String
Sql = "Select ..." "Insert ..." "Update... " "Delete ..."
Dim Cmd As New OleDbCommand(Sql, Cn)

Ejecutar el comando:
Para ejecutar el comando se utilizar el mtodo adecuado en funcin de la consulta establecida.
Es recomendable controlar los errores.
Las consultas de accin: Insert, Delete, Update, devuelven el nmero de registros afectados:
Try
Dim NregAfectados As Integer = Cmd.ExecuteNonQuery
'mostrar el resultado
Catch ex As Exception
MessageBox.Show(ex.Message)
Finally
'Cierra siempre la conexin
'Cn.Close()
End Try

Las consultas de seleccin que devuelven un valor escalar: "Select Count(*) from ...", ...
Dim Num As Integer = CInt(Cmd.ExecuteScalar)

Las consultas de seleccin que devuelven un objeto DataReader: "Select * from ..."
1. Declarar el objeto DataReader
Dim Dr As OleDbDataReader

2. Asignar al objeto DataReader el resultado de la ejecucin del comando.


Es conveniente comprobar si la conexin est abierta
Try
If Cn.State = ConnectionState.Open Then
Dr = Cmd.ExecuteReader
End If
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try

Objeto DataReader. Obtiene un resulset resultado de la ejecucin de un comando de seleccin.


Un objeto DataReader permite la navegacin hacia adelante (Foward Only) y en modo slo lectura
(Read Only), de los registros devueltos por una consulta (resulset).
Los DataReader permanecen conectados durante todo el tiempo que realizan el recorrido por los
registros que contienen, ya que efectan la lectura de la fuente de Datos (BD) fila a fila (registro a
registro).
El uso de este objeto puede incrementar el rendimiento de una aplicacin y reducir la carga del sistema
ya que solo se almacena en el buffer del Cliente una sola fila (registro) cada vez.
No es posible ejecutar ningn comando en una conexin mientras un obj DataReader est activo en esa
conexin. Por lo tanto, se debe cerrar un DataReader, cuando ya no se tienen que procesar ms filas,
para liberar recursos y dejar disponible la conexin para otros comandos.
Propiedades:
IsClosed. True si DataReader est cerrado.
Item(i). Slo lectura. Devuelve el valor de un campo de la fila actual.
Permite acceder a cualquier campo, por su nombre o por el ndice de su columna (comienza por
0).
Es el miembro predeterminado, por lo que se puede omitir.
dr.Item(IdiceColumna)
dr(IdiceColumna)

dr.Item(NombreCampo)

FieldCount. Obtiene el N de campos de la fila actual.


HasRows. Bolean. Obtiene un valor que indica si el DataReader contiene alguna fila.
RecordsAffected. Devuelve el nmero de filas insertadas, eliminadas o actualizadas por la instruccin
SQL
Mtodos:
Read. Desplaza el cursor actual al siguiente registro del resulset permitiendo obtener los valores del
mismo.
Pasa a la fila siguiente y devuelve True si hay ms filas y False si ha llegado al final del
resulset.
La posicin del objeto DataReader en el momento inicial es antes del primer registro, por lo
tanto para recorrer un objeto DataReader debemos comenzar con una llamada al mtodo
Read(), y as situarnos en el primer registro.
Close. Cierrar el objeto, libera todos los recursos asignados a l y hace que la conexin est disponible
para otros comandos.
NextResult. Pasa al siguiente resulset y devuelve True si hay otro resulset.
Desplaza el puntero actual al siguiente conjunto de registros cuando la sentencia SQL
devuelve ms de un conjunto de registros (Ms de una sentencia Select separada por punto y
coma). Como los que pueden devolver un procedimiento almacenado o un procesamiento por
lotes.
GetName(i). Recupera el nombre del campo de ndice i.
GetOrdinal(NombreCampo). Devuelve el ndice de la columna correspondiente al nombre de campo
pasado como argumento.

8
Mtodos de la fila actual leda con Read
IsDBNull(i). Devuelve True si el campo de ndice i contiene un valor DBNul.
If Dr.IsDBNull(i) = True Then ...

GetValue(i). Obtiene el valor de un campo (en su formato nativo).


Da error si el campo es nulo
'recupera el valor de un campo
If Dr.IsDBNull(0) = False Then
Me.TextBox1.Text = Dr.GetValue(0).ToString
End If

GetValues(Matriz). Devuelve los valores de todos los campos de la fila actual en una matriz de objetos.
Este procedimiento es ms lento que el anterior.?
Dim cadena As String
Dim TbCampos(Dr.FieldCount - 1) As Object
'obtiene todos los campos
Dr.GetValues(TbCampos)
'itera todos los campos TbCampos(i)
cadena = ""
For i = 0 To Dr.FieldCount - 1
If Not IsDBNull(TbCampos(i)) Then
cadena = cadena & TbCampos(i) & "-"
End If
Next
Me.TextBox1.Text = cadena

Getxxxx(i). Recupera el valor del campo, con declaracin de tipo. (GetString, GetInt32, ...)
Los Datos obtenidos por un DataReader estn en el formato binario propio del proveedor de
datos. Estos valores se deben convertir a los tipos adecuados, para ello DataReader dispone de
un conjunto de mtodos que permiten obtener los valores de los campos en el tipo de datos
deseado.
GetBoolean(i), GetInt32(i), GetString(i), GetChar(i), etc.
GetFieldsType(i). Devuelve el objeto System.Type del tipo de campo.

9
Procedimientos de lectura del resulset
El procedimiento general es el siguiente:
1.
Abrir la conexin
2.
Crear y ejecutar el comando
3.
Leer los datos, mostrarlos o procesarlos ...
4.
Cerrar la conexin
Leer los datos y mostrar el nombre de los campos y sus valores:
El nmero y nombre de los campos se puede obtener despus de ejecutar el comando.
El valor de los campos se obtiene al ejecutar el mtodo Read del DataReader
1. Leer la siguiente fila.
Cerrar el lector DataReader cuando no haya ms filas
'lee la siguiente fila
If Dr.Read = False Then
MessageBox.Show("no hay ms registros")
Dr.Close()
Else
'mostrar los resultados
End if

2. Mostrar los resultados


'mostrar el nombre de los campos
Label1.Text = Dr.GetName(1)
Label2.Text = Dr.GetName(2)
Label2.Text = Dr.GetName(3)
...
'mostrar el valor de los campos
Txt1.Text = Dr.Item(1).ToString
Txt2.Text = Dr.Item(2)
Txt3.Text = Dr(3)
...
If Dr.IsDBNull(4) = False Then
Txt4.Text = Dr.GetValue(4).ToString 'da error si el campo es nulo
End If

Los pasos 1 y 2 se pueden agrupar:


Dim TbLabel() As Label = {Me.Label2, Me.Label3, Me.Label4,...}
Dim TbCaja() As TextBox = {Me.TextBox1, Me.TextBox2, Me.TextBox3, ...}
If Dr.Read = False Then
MessageBox.Show("no hay ms registros")
Dr.Close()
Else
'mostrar resultados
For i = 0 To Dr.FieldCount - 1
'mostrar nombres de campos
TbLabel(i).Text = Dr.GetName(i)
'mostrar valor de los campos
TbCaja(i).Text = Dr.Item(i).ToString
Next
End if

10
Para leer todos los registros:
'recupera el nombre de los campos y los muestra
For i = 0 To Dr.FieldCount - 1
Me.TxtNombreCampos.AppendText(Dr.GetName(i) & "
Next

")

'recupera el valor de los campos del resulset, fila a fila


'y los muestra en una lista fija
Dim cadena As String
Do While Dr.Read = True
cadena = ""
For i = 0 To Dr.FieldCount - 1
cadena = cadena & Dr.Item(i) & "-"
Next
Me.LstCampos.Items.Add(cadena)
Loop

11

Consultas parametrizadas.
En muchas ocasiones es necesario utilizar consultas SQL con valores de campos variables (o
parmetros). Es decir, un campo podr tomar, en tiempo de ejecucin, distintos valores; como, por
ejemplo, el valor asignado por el usuario.
Ejemplos. De la BD Biblio.mdb:
- Obtener el ttulo de los libros escritos por un autor seleccionado por el usuario.
- Obtener los datos de los libros publicados por la editorial seleccionada por el usuario.
- Obtener el ttulo de los libros publicados, en el ao seleccionado por el usuario, por la editorial
seleccionada tambin por el usuario.
En estos casos el comando que se ha de crear ha de tener parmetros, y utilizar, en la consulta SQL,
unos signos u otros como marcadores de posicin. La sintaxis depende del proveedor de datos.
Los comandos parametrizados son tiles cuando se tiene que realizar el mismo tipo de consulta ms de
una vez, con diferentes valores en los parmetros.

Procedimiento de utilizacin de comandos parametrizados:


1. Crear el comando con los marcadores de posicin
2. Configurar la coleccin de parmetros
3. Ejecutar el comando.
Crear el comando con los marcadores de posicin
Dependiendo del proveedor de datos la sentencia SQL utilizada tendr unos marcadores de posicin u
otros.
Para el proveedor SQL Server .NET, se utiliza @ como marcador de posicin.
Sql = "Select * From Titles Where PubId=@ParName"

Para el proveedor OLE DB .NET, se utiliza ? como marcador


Sql = "Select Title From Titles Where PubID=?

And [Year Published]=?"

Aunque los procedimientos son similares, no son iguales. Aqu se va a describir los utilizados para el
proveedor de datos OLE DB
'Crea el comando con signos de interrogacin como marcadores de posicin
Dim Sql As String
Sql = "Select Title From Titles Where PubID=? And [Year Published]=?"
Dim Cmd As OleDbCommand
Cmd = New OleDbCommand(Sql, Cn)

12
Configurar la coleccin de parmetros
Se deben crear tantos objetos Parameter como parmetros tenga la consulta SQL y luego agregarlos a la
coleccin Parameters del objeto Command, en el mismo orden en que aparecen los parmetros en el
comando SQL.
Existen 3 modos de crear un objeto Parameter:
a) Utilizando el constructor del objeto Parameter
'define el parmetro
Dim Par As New OleDbParameter("ParIdEditorial", OleDbType.Integer)
Par.Value = 1 'asigna valor inicial. No es necesario
Cmd.Parameters.Add(Par) 'aade el parmetro a la coleccin de parmetros
'define el 2parmetro
Dim Par2 As New OleDbParameter("ParAoPubli", OleDbType.SmallInt)
Cmd.Parameters.Add(Par2) 'aade el parmetro a la coleccin de parmetros

b) Utilizando el mtodo CreateParameter del objeto Command


No es obligatorio definir ni el nombre del parmetro ni el tipo.
'configura el 1er parmetro
Dim Par As OleDbParameter 'declara el parmetro
Par = Cmd.CreateParameter 'crea el parmetro
Par.Value = 1 ' no es necesario
Cmd.Parameters.Add(Par) aade el parmetro a la coleccin
'configura el 2 parmetro
Dim Par As OleDbParameter = Cmd.CreateParameter
Cmd.Parameters.Add(Par)

c) Invocando al nuevo mtodo AddWithValue de la coleccin Parameters


Introduce nombre y valor en el mtodo AddWithValue de la coleccin Parameters
'invoca al mtodo AddWithValue
Cmd.Parameters.AddWithValue("ParIdEditorial", 1)
Cmd.Parameters.AddWithValue("ParAoPubli", 1992)

Ejecutar el comando
- Asignar valor a los parmetros
- Ejecutar el comando
'Asigna valor a los paarmetros
Dim Valor1 As Integer = Me.TextBox1.Text
Cmd.Parameters(0).Value = Valor1
Dim Valor2 As Short = Me.TextBox2.Text
Cmd.Parameters(0).Value = Valor2
'Ejecuta el comando
Dim Dr As OleDbDataReader
Dr = Cmd.ExecuteReader
'obtiene el resultado

También podría gustarte