You are on page 1of 35

Visual Basic - Guía del Estudiante Cap.

13
Acceso a Bases de Datos remotas mediante el motor Jet
ODBCDirect
Acceso a Bases de Datos remotas mediante objetos RDO

Acceso a Bases de Datos remotas mediante el motor Jet


ODBCDirect

Hasta ahora todos los accesos realizados a una base de datos los hemos realizado
directamente a través del Motor de bases de Datos Microsoft JET. Este motor de bases de
datos abre, lee y graba el fichero .MDB (o el dBase, FoxPro, Paradox, etc.) de la misma forma
que un editor de textos puede abrir, leer o escribir un fichero creado por el mismo o por otros
editores conocidos.

Las bases de datos (las buenas) tienen unas herramientas comunes para manejarlas. Estas
herramientas son, por una parte el lenguaje SQL que puede dar instrucciones para leer o
escribir una base abierta, mediante un lenguaje común para todas las bases, y por otra, la
herramienta que abre esa base de datos y nos hace verla, desde el exterior, bajo una forma
única para todas las bases: el ODBC.

El ODBC es una herramienta que nos permite ver a todas las bases de una forma única. No es
un lenguaje común a todas las Bases de datos. Ese es el SQL. Es la interface que adapta a
una base de datos para que nos podamos entender con ella en SQL. Por lo tanto es fácil
pensar que esa interface deberá fabricarla el mismo fabricante que ha realizado la base de
datos. El lenguaje SQL es conocido por todo el mundo, pero la forma interna de trabajar una
base de datos solamente la conoce su fabricante. Por eso, el Driver ODBC que es el que nos
permite adaptar las particularidades de esa base de datos al lenguaje común, deberá
suministrarlo el fabricante de la base.

Microsoft desarrolló varios drivers para otras tantas bases de datos y hojas de cálculo. Entre
ellas para Access y Excel, dBase y FoxPro. También lo desarrolló para bases de datos tan
populares como Oracle. Ese driver hay que instalarlo en el ordenador, aunque Windows instala
algunos por defecto.

Veamos ahora otro elemento fundamental para el trabajo con ODBC: la conexión. La conexión
ODBC es el conjunto de datos que hay que aportarle a Windows para que pueda enlazar
nuestra aplicación con la base de datos. Estos datos son, al menos:

El nombre de la conexión, por el cual la podremos nombrar para referirnos a ella.


El driver que debe utilizar para entenderse con la base de datos
El nombre (y Path) de la base de datos que queremos manejar con esa conexión.

La conexión ODBC no la realiza Visual Basic. La realizará Windows. Veamos como podemos
establecerla.

Vaya a Inicio | Configuración | Panel de Control | ODBC de 32 Bits. Haga doble click y le
aparecerá un cuadro como el de la figura 13-1. En este cuadro figuran todos los enlaces que
están establecidos. Estos enlaces puede establecerlos para un usuario (DSN de usuario), de
sistema o de archivo. La elección de uno u otro dependerá de los permisos de acceso que
quiera establecer (y eso es, de momento, para nota). En cualquier caso, todas los enlaces
ODBC que establezca funcionarán del mismo modo, exceptuando que puede otorgar unas
prerrogativas distintas de uso, dependiendo de como lo haya abierto.

Observe uno que figura en la lista: Luki. En esa línea figura otro dato: Microsoft Access
Driver.(*.mdb) Esto significa que el enlace de nombre Luki está usando el driver ODBC de
Access. Y significa también que si queremos llamar a esa conexión deberemos llamarla por su
nombre : Luki

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 1


Fig. 13-1 Creación de un enlace ODBC. Muestra las conexiones existentes (una vez creada la
conexión Luki)

Sigamos con la creación del enlace ODBC. Para crear uno nuevo, haga click en el botón
Agregar de la figura 13-1. Le aparecerá un cuadro donde le pide el driver que quiere utilizar.

Fig. 13 – 2 Elección del driver ODBC

Haciendo click en Finalizar, le pedirá el nombre del nuevo enlace, un comentario, (no es
necesario introducirlo), y la base de datos con la que quiere enlazar

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 2


Fig. 13-3 Introducción del nombre del enlace, comentario (descripción) y base de datos
asociada al enlace ODBC

Veamos los datos que hemos introducido en nuestra conexión “Luki”

Nombre del Origen de datos. Luki


Descripción (Opcional) Conexión ODBC Cap. 21

Haciendo click en Base de Datos | Seleccionar nos muestra un cuadro de diálogo donde
`podemos buscar la base de datos. Se elige la base de datos deseada. Hacemos click en
ACEPTAR y ya está creada la nueva conexión.

La base de datos del sistema deberá elegirla para poder introducir usuarios con distintas
atribuciones de acceso a la base de datos. Si no introduce esta base de datos de sistema,
deberá trabajar sin restricción de acceso.

Una vez creada la conexión podemos utilizarla para conectar nuestra aplicación con la base de
datos. El proceso para ello consiste en algo parecido a lo que hacíamos trabajando con el
motor Jet en el espacio de trabajo Microsoft Jet, pero de distinta forma. En ese entorno se
manejaba la base de datos creando un objeto Database, que manipulaba el fichero de la base
de datos directamente. En este caso, la base de datos se maneja mediante un objeto
Connection.

El trabajar sobre una conexión nos aporta mayor versatilidad a las aplicaciones. Piense por
ejemplo un caso en el que se emplea una base de datos Access. Si quisiésemos ampliar las
prestaciones de la base de datos de esa aplicación posiblemente pensaríamos en migrar la BD
a Oracle o SQLServer. Si atacamos a la base de datos a través de ODBC solamente
deberíamos cambiar la conexión, tal como vimos más atrás. Nuestro programa seguiría
llamando a la misma conexión ODBC, pero esta conexión, ahora, abriría una base Oracle o
SQLServer en vez de la Access que abría originalmente. No necesitaríamos realizar ninguna
modificación en nuestro programa.

Este razonamiento es válido para cualquier sistema de acceso a bases de datos a través de
ODBC. (RDO ó ADO) Sin embargo el ODBCDirect tiene una ventaja `para los que trabajamos
normalmente con DAO: usa los mismos nombres para casi todos los métodos y funciones, por
lo que el cambio de código es mínimo. El cambio se limita prácticamente a crear el objeto
Connection en vez del objeto Database. Comencemos a ver esto con u ejemplo. Es un
ejemplo uy simple, en el que abrimos una base de datos Access llamada Alumnos.Mdb que
tiene una tabla llamada Personas. Creamos la conexión Luki tal como se describió mas
atrás. La tabla personas tiene solamente tres campos: ID_Alumno, Nombre y Apellidos.
Creamos una interface gráfica sencilla

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 3


Fig. 13-4 Nuestra primera aplicación con ODBCDirect

Mediante esta sencilla aplicación queremos visualizar los datos existentes, añadir nuevos
registros y borrar el registro actual. Veamos el código con los comentarios oportunos.

General/Declaraciones
Option Explicit 'Declaramos las variables tipo objeto
Dim MiSesion As Workspace
Dim MiConexion As Connection
Dim RsODBC As Recordset

Private Sub BCrearConexion_Click()


'Se le dice al DBEngine que debe trabajar en el espacio de trabajo ODBCDirect
DBEngine.DefaultType = dbUseODBC
Set MiSesion = Workspaces(0)
'Se crea el objeto conexión
Set MiConexion = MiSesion.OpenConnection("Conexion1", dbDriverNoPrompt, False,
"ODBC;DSN=Luki")
´Se crea el objeto Recordset
Set RsODBC = MiConexion.OpenRecordset("Personal", dbOpenDynamic, dbRunAsync,
dbPessimistic)
'Es necesario recorrer el recordset para conocer cuantos registros tiene (Es Dynaset)
RsODBC.MoveLast
RsODBC.MoveFirst
If RsODBC.AbsolutePosition <> -1 Then
LNumRegs = RsODBC.RecordCount
LNumReg = RsODBC.AbsolutePosition + 1
PresentaDatos
Else
MsgBox "La base de datos no tiene ningún registro"
End If
End Sub

Public Sub PresentaDatos()


TB_ID = "": TB_Nombre = "" : TB_Apellido = ""
TB_ID = RsODBC!ID_Alumno
TB_Nombre = RsODBC!Nombre
TB_Apellido = RsODBC!Apellidos
LNumReg = RsODBC.AbsolutePosition + 1

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 4


End Sub
Private Sub BEliminar_Click()
RsODBC.Delete
LNumRegs = RsODBC.RecordCount
LNumReg = RsODBC.AbsolutePosition + 1
If RsODBC.AbsolutePosition <> -1 Then
RsODBC.MoveFirst
PresentaDatos
End If
End Sub

Private Sub BGuardarDatos_Click()


RsODBC.AddNew
RsODBC!ID_Alumno = TB_ID
RsODBC!Nombre = TB_Nombre
RsODBC!Apellidos = TB_Apellido
RsODBC.Update
LNumRegs = RsODBC.RecordCount
LNumReg = RsODBC.AbsolutePosition + 1
End Sub

Private Sub BMas_Click()


If RsODBC.AbsolutePosition <> -1 Then
RsODBC.MoveNext
If RsODBC.AbsolutePosition <> -1 Then
PresentaDatos
Else
RsODBC.MoveLast
PresentaDatos
End If
End If
End Sub

Private Sub BMenos_Click()


If RsODBC.AbsolutePosition <> -1 Then
RsODBC.MovePrevious
If RsODBC.AbsolutePosition <> -1 Then
PresentaDatos
Else
RsODBC.MoveFirst
PresentaDatos
End If
End If
End Sub

Private Sub BMMas_Click()


If RsODBC.AbsolutePosition <> -1 Then
RsODBC.MoveLast
PresentaDatos
End If
End Sub

Private Sub BMMenos_Click()


If RsODBC.AbsolutePosition <> -1 Then
RsODBC.MoveFirst
PresentaDatos
End If
End Sub

Private Sub BNuevoReg_Click()


Limpia

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 5


End Sub
Public Sub Limpia()
TB_ID = ""
TB_Nombre = ""
TB_Apellido = ""
End Sub

Observe que casi todo el código es igual que el que escribiríamos si hubiésemos utilizado el
espacio de trabajo Microsoft Jet. Solamente hemos utilizado código distinto el procedimiento
BCrearConexion_Click. Vamos a analizar las instrucciones de ese procedimiento que son
distintas a las que estamos acostumbrados a manejar

DBEngine.DefaultType = dbUseODBC
Vea la propiedad DefaultType en el Capítulo 20. Tenga en cuenta que el ODBCDirect lo
ejecuta el motor Jet (que como recordará es el objeto DBEngiine). La propiedad DefaulType
debemos igualarla a dbUseODBC para que trabaje en el espacio de trabajo ODBCDirect. Si
no le diésemos ningún valor a esa propiedad, tomaría el otro valor posible (dbUseJet) que es
su valor por defecto. Por eso, cuando utilizábamos los métodos CreateDataBase u
OpenDatabase no necesitábamos darle ningún valor a esa propiedad.

Set MiConexion = MiSesion.OpenConnection("Conexion1", dbDriverNoPrompt, False,


"ODBC;DSN=Luki")

Vea mas abajo la información de OpenConnection para ver los parámetros que hay que
pasarle a este método.

Set RsODBC = MiConexion.OpenRecordset("Personal", dbOpenDynamic, dbRunAsync,


dbPessimistic)

Vea mas abajo una ampliación del método OpenRecordset

Método OpenConnection
Es un método del Workspace que solamente es aplicable cuando el DBEngine está trabajando
en el espacio de trabajo ODBCDirect. Abre un objeto Connection usando un origen de datos
ODBC ya creado.

El objeto Connection sería el equivalente en DAO al objeto Database. Debemos declararlo


antes de usarlo

Dim MiConexion as Connection

Si MiSesion es el Workspace que queremos usar, la sintaxis de OpenConnection es la


siguiente:

Set MiConexion = MiSesion.OpenConnection (Nombre, Opciones, Sólolectura y Conectar)

En el ejemplo:
Set MiConexion = MiSesion.OpenConnection("Conexion1", dbDriverNoPrompt, False,
"ODBC;DSN=Luki")

Veamos que son los parámetros Nombre, Opciones, Sólolectura y Conectar

Nombre es el nombre de la conexión (no se debe confundir con el nombre del objeto
Connection que es MiConexion, y que es el nombre por el que nos tendremos que referir a esa
conexión en toda la aplicación. Nombre no lo usará normalmente)

El parámetros Nombre puede ser una cadena cualquiera, o el nombre del enlace ODBC
establecido en Windows (que en nuestro ejemplo sería Luki). Si opta por poner una cadena
cualquiera (como hicimos en el ejemplo, Conexión1) deberá poner el nombre del enlace
ODBC en el parámetro Conectar. Si opta por poner el nombre del enlace ODBC, Visual Basic

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 6


interpreta que debe conectar a través de ese enlace y ya no necesita poner ningún valor al
parámetro Conectar.

Opciones Este parámetro es para definir que tipo de respuesta va a dar el administrador del
controlador de ODBC para solicitar al usuario información sobre la conexión (Nombre del
origen de datos (DSN), nombre del usuario y contraseña). Puede tomar uno de los siguientes
valores:

DbDriverNoPrompt El administrador del controlador de ODBC toma los datos de los


parámetros Nombre y Conectar para saber cual es el enlace ODBC que debe usar. Si
no proporciona suficiente información, se producirá un error de tiempo de ejecución.

DbDriverPrompt El administrador del controlador de ODBC muestra el cuadro de


diálogo de ODBC, que muestra todos los enlaces ODBC existentes. La conexión se
hace con el DSN que selecciona el usuario en ese cuadro de diálogo.

Fig. 13.5 Cuadro de diálogo de ODBC

Una vez seleccionada la conexión, aparecerá otro cuadro solicitando el nombre de inicio de
sesión y la contraseña. En resumen, con este parámetro DbDriverPrompt forzamos al
programa a que utilice los recursos Windows para seleccionar el enlace ODBC

DbDriverComplete (Este es el valor predeterminado). Se comporta (aparentemente)


como si se pone DbDriverNoPrompt

DbDriverCompleteRequired Al igual que la anterior, esta opción se comporta


(aparentemente) como si se pone DbDriverNoPrompt

Sólolectura (Opcional). True si la conexión se va a abrir con acceso de sólo lectura y False si
la conexión se va a abrir para acceso de lectura/escritura (predeterminado)

Conectar (Opcional si se ha puesto el nombre del enlace en el parámetro Nombre). Este


parámetro está formado por varias partes. Una, obligatoria, que contiene la expresión "ODBC;"
Otra parte obligatoria, si no ha puesto en el parámetro Nombre el nombre del enlace ODBC es

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 7


"DSN = NombredelaConexión;" Si desea especificar el usuario propietario de esa conexión
debe añadir "UID = usuario;" y como ese usuario tendrá una contraseña, deberá añadirla
también "PWD = contraseña;" También puede indicar cuanto tiempo debe esperar el
administrador del controlador de ODBC para generar un error en caso de que no conteste el
sistema a la petición ODBC. Este tiempo deberá introducirlo con la expresión
"LOGINTIMEOUT = segundos;" Observe que cada una de estas partes lleva un
identificador y un dato, ambos separados por un signo =, y siempre terminan con el signo
punto y coma (;)

Si omite los parámetros UID y/o el PWD, estos datos se obtendrán de las propiedades
UserName y Password del objeto Workspace.

Método OpenRecordset
Este método ya se estudió en el capítulo anterior, pero se van a ver ciertas peculiaridades que
tiene cuando se abre un recordset en el espacio de trabajo ODBCDirect

En este caso es el objeto Connection quien abre el recordset.:

Set MiRecordset =
= MiConexion.OpenRecordset (Origen, Tipo, Opciones, Bloquearmodificaciones)

Origen Puede ser un nombre de tabla, de una consulta o una instrucción SQL que devuelva
registros.
Tipo Indica el tipo de recordset que queremos crear. El espacio de trabajo ODBCDirect no
permite recordsets tipo Tabla. Los tipos que se pueden elegir son:

DbOpenDynamic Abre un objeto Recordset de tipo Dynamic, que es parecido a un


cursor dinámico ODBC
DbOpenDynaset Abre un objeto Recordset de tipo Dynaset, similar al estudiado en el
capítulo 20 para el espacio de trabajo Microsoft Jet
DbOpenSnapshot Abre un objeto Recordset de tipo Snapshot,
dbOpenForwardOnly Abre un objeto Recordset de tipo Forward-only, que tiene la
particularidad de que no permite movernos en el recordset de adelante hacia atrás.
Este es el tipo que creará por defecto si no se especifica nada en el parámetro Tipo.

Opciones Debe indicar uno de estos dos valores (si no pone alguno de ellos da error):

DbRunAsync Ejecuta una consulta asíncrona, que es la forma normal de trabajar del
ODBC. Esto permite a su aplicación seguir procesando otras instrucciones mientras se
ejecuta la consulta en segundo plano (Vea mas adelante la propiedad StillExecuting
dbExecDirect Ejecuta una consulta saltando el método SQLPrepare y llamando
directamente al método SQLExecDirect. Utilice esta opción sólo cuando no se abra un
objeto Recordset basándose en una consulta de parámetros. Para obtener más
información, consulte la "Referencia del programador de Microsoft ODBC 3.0."

Bloquearmodificaciones Este parámetro es fundamental si quiere escribir en la base de


datos, pues si lo omite le pone por defecto que la base es de solo lectura. Mediante este
parámetro va a determinar el tipo de bloqueo de la base de datos para entornos de trabajo
multiusuario. Puede poner uno de estos valores:

DbReadOnly (Predeterminado) No permite que los usuarios hagan cambios en los


registros del Recordset
DbPessimistic Permite cambiar datos y añadir registros en el recordset, utilizando el
criterio de bloqueo pesimista. Esto significa que bloquea la página donde se encuentra
el registros desde que se ejecuta el método Edit hasta que se ejecuta el Update. Es el
criterio mas seguro de bloqueo de datos, pero debe tener en cuenta que tiene la base
bloqueada desde el Edit hasta el Update. Si hace bloqueo pesimista, procure que las
instrucciones entre uno y otro no tengan ningún tiempo de espera, por ejemplo a que el

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 8


usuario introduzca un dato. (El tamaño de una página depende de la base de datos
que esté usando. En Access es de 2048 Bytes. Esto significa que solamente tendrá
bloqueada una parte relativamente pequeña de la base de datos, pudiendo modificar
otros registros que estén fuera de ese segmento de 2 Kbytes. Lógicamente este
bloqueo solamente tendrá efecto cuando esté trabajando en un entorno multiusuario.

DbOptimistic Permite cambiar datos y añadir registros en el recordset, utilizando el


criterio de bloqueo optimista. El bloqueo optimista significa que solamente estará
bloqueada la página que contiene el registro mientras se ejecuta el método Update.
Esto puede ocasionarle que, si están dos usuario trabajando sobre el mismo registro,
se introduzca un dato erróneo. Parece así en principio que no se debe usar, pero todo
va a depender de la aplicación, de sus datos, y de la probabilidad de que ocurra esa
colisión. La ventaja que tiene es que tiene menos tiempo bloqueada la página de la
base de datos.

dbOptimisticValue Utiliza la concurrencia optimista basándose en valores de fila.


Funciona de forma similar al dbOptimistic.

dbOptimisticBatch Activa la actualización optimista por lotes.

Actualización por lotes. Modelo de cursor para clientes que trabajan con cursores, pero no
mantienen bloqueos en el servidor o ejecutan actualizaciones por fila. En su lugar, el cliente
actualiza muchas filas que están almacenadas en el búfer local y después ejecuta una
actualización por lotes. Este modelo de cursor también permite al cliente cancelar la
conexión con el servidor y volverla a establecerla con el mismo servidor o con otro diferente.

Para utilizar la actualización por lotes en DAO 3.5, debe utilizar un espacio de trabajo de
ODBCDirect, la propiedad DefaultCursorDriver se debe establecer a
dbUseClientBatchCursor en el momento de abrir la conexión y se debe abrir el Recordset
con el argumento de tipo de bloqueo del método OpenRecordset establecido a
dbOptimisticBatch.

Propiedad StillExecuting
Cuando abrimos una conexión mediante OpenConnection, un QueryDef o creamos un
recordset y le ponemos en Opciones DbRunAsync, la operación se realiza de forma
asíncrona, por lo tanto no sabemos cuando tendremos disponible el objeto a crear o los datos
de la consulta. Para poder controlar si la operación se está realizando todavía leeremos la
propiedad StillExecuting, que devolverá True si todavía se está ejecutando, y False si ha
terminado. Basta con hacer un bucle del tipo

Do While MiConexion.StillExecuting = True


DoEvents
Loop

Mientras la propiedad StillExecuting sea True, no se puede tener acceso a ningún objeto
devuelto. Por ejemplo, no pretenda crear un recordset con MiConexion Mientras que
StillExecuting sea True, pues MiConexión no existe aún.

Esta propiedad puede ser muy útil cuando tiene consultas encadenadas y necesita esperar a
que termine una para comenzar con la siguiente.

StillExecuting se utiliza con los objetos y para las operaciones siguientes:

Objeto Connection, para controlar que aún se está ejecutando uno de los métodos Execute
u OpenConnection
Objeto QueryDef, para comprobar su método Execute
Recordset, donde podrá comprobar si aún se están realizando los métodos Move,
NextRecordset u OpenRecordset

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 9


Para ver el valor que tiene la propiedad StillExecuting deberá poner el nombre del objeto que
quiere comprobar (Connection, QueryDef o Recordset) después de haber iniciado uno de los
métodos citados anteriormente. Por ejemplo, para esperar a que se haya creado el objeto
Connection MiConexion, haremos un bucle de la siguiente forma

Set MiConexion = MiSesion.OpenConnection("Luki1", dbDriverNoPrompt)


Do While MiConexion.StillExecuting = True
Aquí las instrucciones que quiera
Loop

Método Cancel
Cancela la ejecución de un método asícrono de llamada. Sólo funciona espacios de trabajo
ODBCDirect.

Sintaxis objeto.Cancel

La sintaxis del método Cancel consta de las siguientes partes:

Objeto puede ser:


Connection para cancelar el método Execute u OpenConnection
QueryDef, para cancelar el método Execute
Recordset para cancelar el método OpenRecordset

El método Cancel solamente sirve para cancelar la ejecución de una llamada asíncrona de los
métodos Execute, OpenConnection u OpenRecordset que se hayan invocado con la opción
dbRunAsync. Cancel devolverá un error de tiempo de ejecución si en el método que está
intentando finalizar no se utilizó dbRunAsync.

Objetos Database y QueryDef en el espacio de trabajo ODBCDirect


Repasemos la estructura jerárquica de los objetos de acceso a datos en el espacio de trabajo
ODBCDirect. Podemos ver que siguen existiendo, aparte de los ya estudiados en este capítulo,
dos objetos que ya nos son conocidos: el QueryDef y el Database. Veamos cada uno de ellos.

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 10


Fig. 13-6 Estructura jerárquica de los objetos de acceso a datos en el espacio ODBCDirect

Objetos QueryDef en el espacio de trabajo ODBCDirect


Habíamos visto en el capítulo 20 que un QueryDef era una consulta cuando todavía no estaba
guardada en el disco. Es decir, un QueryDef es una consulta en memoria RAM. Ese QueryDef
se transforma en una consulta de la base de datos una vez que se cierra el objeto Database.

En el espacio de trabajo ODBCDirect no se pueden crear bases de datos. Se pueden crear


objetos QueryDef, que en este caso serán objetos efímeros, que solamente existirán en la
memoria RAM, desapareciendo en el momento que cerremos ese QueryDef o cerremos la
aplicación.
Puede crear un QueryDef para crear posteriormente a partir de él un Recordset con el que
puede presentar o escribir el contenido de los registros. En el siguiente ejemplo hemos abierto
la conexión, y como paso previo a la creación del recordset hemos creado un QueryDef con
todos aquellos registros cuyo campo Apellidos sea igual a Alvarez Pérez. Una vez creado ese
QueryDef, hemos creado un recordset a partir de él. No tiene mucho sentido hacer esto ya
que podríamos crear directamente el recordset imponiendo esa condición en el campo
Apellidos. Se expone aquí con fines didácticos, no prácticos.

DBEngine.DefaultType = dbUseODBC
Set MiSesion = Workspaces(0)
Set MiConexion = MiSesion.OpenConnection("Conexion1", dbDriverNoPrompt, False,
"ODBC;DSN=Luki")
Set MiConsulta = MiConexion.CreateQueryDef ("Pepito", "Select * From Personal Where
Apellidos = "Alvarez Pérez")
Set RsODBC = MiConsulta.OpenRecordset(dbOpenDynaset, dbRunAsync, dbOptimistic)
If RsODBC.AbsolutePosition <> -1 Then
RsODBC.MoveLast
RsODBC.MoveFirst
LNumRegs = RsODBC.RecordCount
LNumReg = RsODBC.AbsolutePosition + 1
PresentaDatos
Else
MsgBox "El recordset no tienen ningún registro"
End If

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 11


Puede apreciar en la fig. 13-6 otro objeto que está jerárquicamente debajo del QueryDef. El
Objeto Parameter. Este objeto sirve para cambiar los parámetros que se le pasan al QueryDef
para crearlo. Le remito a la ayuda de VB para mayor explicación de este objeto.

El objeto Database en el espacio de trabajo ODBCDirect


En el espacio ODBCDirect puede también abrir un objeto Database en vez de un objeto
Connection. La diferencia a la hora de crear un objeto Database (abrir una base d e datos)
entre el espacio de trabajo Microsoft Jet y ODBCDirect es que en el primero abrimos
directamente el fichero de la base de datos, y en el segundo, abrimos el fichero que indique el
enlace ODBC. Deberemos suministrarle información del enlace ODBC que debe usar. La
sintaxis sigue siendo igual que en el espacio de trabajo Microsoft Jet:

Set MiBaseDatos = MiSesion.OpenDatabase (Nombre, Opciones, Sólolectura, Conexión)

Para indicarle el enlace ODBC que debe usar puede hacerlo de las dos formas que venimos
viendo para los parámetros Nombre y Conexión. Si indica el nombre del enlace en el
parámetro Nombre lo aceptará y será necesario poner el parámetro Conexión. Si `pone un
nombre cualquiera en el parámetro Nombre deberá indicar el nombre del enlace en el
parámetro Conexión.

Esta posibilidad de crear un objeto Database nos aproxima aún más al código empleado en el
espacio de trabajo Microsoft Jet. Por lo tanto puede ser muy útil usar este objeto en aquellos
casos en los que ya se había escrito el código, y pasamos posteriormente a usar ODBC.

DBEngine.DefaultType = dbUseODBC
Set MiSesion = Workspaces(0)
'En la siguiente línea le pasamos el nombre del enlace ODBC en el parámetro Nombre
Set MiBaseDatos = MiSesion.OpenDatabase("Luki", dbDriverNoPrompt)
'Pero podríamos haberselo pasado en el parámetro Conexión y ponerle como parámetro
'nombre cualquier cadena de caracteres
Set MiBaseDatos =
MiSesion.OpenDatabase("BaseDatos1", dbDriverNoPrompt, False, "ODBC;DSN=Luki")
'Ahora creamos el recordset, como en los otros casos
Set RsODBC = MiBaseDatos.OpenRecordset("Personal", dbOpenDynaset, dbRunAsync,
dbOptimistic)
If RsODBC.AbsolutePosition <> -1 Then
RsODBC.MoveLast
RsODBC.MoveFirst
LNumRegs = RsODBC.RecordCount
LNumReg = RsODBC.AbsolutePosition + 1
PresentaDatos
Else
MsgBox "La base de datos no tiene ningún registro"
End If

Mediante los ejemplos expuestos en este capítulo espero que el alumno comprenda como
trabaja DAO a través de ODBC, mediante el ODBCDirect.
No olvide que sigue tratándose de DAO, y que por lo tanto deberá poner la misma referencia
(En Proyecto | referencia) que en el caso del DAO trabajando en el espacio de trabajo
Microsoft Jet. En la siguiente parte de este capítulo se estudiarán los objetos RDO, objetos
que trabajan exclusivamente a través de ODBC. Con las ideas captadas hasta aquí verá que
es sencillo abordar estos nuevos objetos.
Visual Basic - Guía del Estudiante Cap. 13 Continuación
Acceso a Bases de Datos remotas mediante objetos RDO

En la primera parte de esta capítulo hemos visto como acceder a bases de datos a través de
ODBC usando el motor JET. El acceso se realizaba mediante ODBCDirect, modo de
operación del motor JET, y podíamos usar la misma sintaxis y objetos que habíamos visto con
los objetos DAO. También vimos como crear un enlace ODBC, enlace que vamos a utilizar en

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 12


este capítulo. Como ya se explicó en el capítulo anterior, damos por supuesto que el alumno
conoce como crear ese enlace.

Los objetos RDO se crearon para cubrir el hueco que tenía VB para conectar con bases de
datos distintas a las que trabaja el motor JET. (Access, dBase, FoxPro, etc.). Esta forma de
trabajar nos permite enlazar con bases de datos tipo Oracle o SQLServer, pero también nos
permite trabajar con Access, dBase o FoxPro, que también tienen su propio driver ODBC.

Lo primero que nos encontramos al trabajar con RDO es que es más lento que DAO. Si
creamos dos aplicaciones que trabajen sobre una base Access, una directamente a través de
DAO y otra a través de RDO, observaremos que la primera accede a la BD con una rapidez
mayor que la segunda. Normal, no es lo mismo abrir un fichero y leerlo (que es lo que hace
DAO) que pasar unos parámetros a otro programa (Driver ODBC de Access) para que este
abra el fichero, obtenga los datos y nos los pase. Lo mismo podemos decir cuando tenemos
que contar registros, movernos de un registro a otro, editar o añadir nuevos registros. Esa falta
de rapidez es el coste de la tecnología de bases abiertas.

Lo segundo que nos va a llamar la atención es el nombre de los objetos de acceso a datos.
Una vez que nos habíamos familiarizado con palabras como Recordset, DataBase o Dynaset,
nos las cambian por rdoResultset, rdoConnection o Keyset respectivamente. Y lo peor no es
solamente tener que aprender sus nombres, sino que en una aplicación hecha en DAO que
sea necesaria cambiarla a RDO, nos vemos obligados a retocar la mayor parte de las líneas
de código (Cosa que no ocurría con ODBCDirect)

Y lo tercero, RDO no tiene la posibilidad de crear bases de datos como hacíamos en DAO.
Normal, ya que en este caso no trabajamos directamente sobre la BD sino sobre la conexión
ODBC que Windows realizó a una base de datos. Podemos añadir mas desventajas de RDO:
no puede contar los registros que tiene, tiene un comportamiento muy irregular con la
propiedad AbsolutePosition, y varios detalles que procuraremos explicar en este capítulo para
ahorrar al alumno el trabajo de tener que experimentarlos por sí mismo. (Aunque, consejo de
viejo profesor, es la forma más segura de aprenderlos).

Tras estos inconvenientes parece lógico encontrar alguna contrapartida positiva. Por ejemplo
poder conectar con cualquier tipo de base de datos, pudiendo incluso realizar la aplicación
atacando una base Access, para luego trabajar con una base SQLServer u Oracle sin variar ni
una línea de código. Esa debería ser la gran ventaja de RDO. Pero lamentablemente, y en
contra de toda teoría de ODBC, no es cierto. Si preparamos una aplicación en RDO trabajando
con una base Access y pretendemos cambiar la base por otra SQLServer, observaremos que
lo que funciona perfectamente en la primera no funciona en la segunda. (Y esto no es teoría.
Es simplemente experiencia del autor). ¡Y Access y SQLServer son del mismo fabricante!. La
razón está en que los drivers de una base y otra no trabajan exactamente igual. Tampoco son
iguales las protecciones y los permisos de acceso. Consejo de viejo profesor: Si va a trabajar
con una determinada base de datos a través de RDO comience el proyecto usando esa base
de datos. Y puestos a dar consejos, si piensa usar SQLServer u Oracle y si la aplicación va a
escribir datos en la base no use RDO. Si solamente los va a leer no tendrá problemas. Y si
tiene problemas nadie se los va a resolver, argumentando que deje RDO y use ADO. De hecho
RDO ya se ha quedado obsoleto al nacer ADO. Pero eso será objeto de otro capítulo de esta
Guía del Estudiante y hoy nos toca aprender RDO. Comencemos.

RDO y DAO. Comparación de sus objetos. El control RemoteData

Al igual que DAO, RDO tiene objetos de acceso a datos, que deberemos declarar y crear.
Mediante estos objetos podemos leer y escribir datos en una BD mediante código. También, al
igual que en DAO existía el Control Data, con el que podíamos acceder a la base de datos sin
escribir ni una línea de código, en RDO existe un control similar: el Control RemoteData. El
funcionamiento es similar, pero las propiedades son distintas y tienen distintos nombres.
Mediante el control RemoteData podemos enlazar una base de datos a los típicos controles
enlazados a datos (Label, TextBox, DBGrid), pero en este caso se enlazan a través de una
conexión ODBC, por lo que es fácil pensar que las propiedades de este control y los valores
que deben tomar son distintas a los del control Data. Como es mucho más sencillo (sencillo no

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 13


quiere decir mejor) usar el control RemoteData que trabajarse con código los objetos de
acceso a datos, vamos a comenzar estudiando este control.

Pero antes vamos adelantar la equivalencia entre los objetos DAO y los objetos RDO. La lista
siguiente está copiada literalmente de la información de Microsoft MSDN Library Visual Studio,
información que merece la pena instalarla en su ordenador pese a lo que ocupa.

Objetos de datos remotos y los objetos de DAO/Jet equivalentes


Objeto de RDO Objeto de DAO/Jet equivalente
rdoEngine DBEngine
rdoError Error
rdoEnvironment Workspace
rdoConnection Database
rdoTable TableDef
No está implementado Index
rdoResultset Recordset
No implementado Tipo Table
Tipo Keyset Tipo Dynaset
Tipo static Tipo Snapshot
Tipo dynamic (ninguno)
Tipo forward-only Tipo forward-only
No implementado (*) User
RdoColumn Field
rdoQuery QueryDef
rdoParameter Parameter
No implementado (**) Relation
No implementado (*) Group
Control RemoteData Control Data

(*) En RDO, los usuarios y grupos de usuarios son precisamente los que lleve implícitos la
conexión ODBC.
(**) Al no trabajar directamente sobre la base de datos, no se pueden crear relaciones en ella.

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 14


El control RemoteData
Este control nos permite crear una aplicación de acceso a datos completa sin utilizar código.
Eso sí, será necesario tener una conexión ODBC hecha, ya que el control RemoteData no abre
un fichero de BD sino una conexión ya establecida.
No está normalmente en la caja de herramientas, por lo que habrá que añadirlo en Proyecto |
Componentes introduciendo el Microsoft Remote Data Control 6.0 El control Remote Data
tiene un aspecto similar al control Data, tanto en la caja de herramientas como en el
formulario:

El control RemoteData toma por defecto el nombre MSRDCx.

Algunas Propiedades del Control RemoteData

DatasourceName

Devuelve o establece el nombre del origen de datos (DSN). El DSN No es más que el nombre
de la conexión ODBC.

Esta propiedad se puede dejar en blanco si la propiedad Connect del control identifica un
nombre de origen de datos (DSN) registrado en el Registro de Windows.

Sintaxis NombredelControlRDO.DatasourceName = MiConexión

Puede cambiarse en tiempo de ejecución. En este caso, inmediatamente debe utilizar el


método Refresh para abrir la nueva conexión con la base de datos.

Puede leer el valor de esta propiedad. Le devolverá precisamente el DNS que está utilizando.
Esta propiedad sólo le devolverá un valor si ha introducido previamente algún valor en la
propiedad DatasourceName. No le devolverá valor alguno si ha introducido la conexión a
través de la propiedad Connect.

Propiedad Connect
Esta propiedad cumple la misma función que la anterior, pero por otro camino. Mediante la
propiedad Connect le introducimos al control RemoteData la información necesaria para abrir
la conexión, incluyendo en esta información, no solamente el nombre de la conexión, como
hacíamos con la propiedad DatasourceName, sino ampliarla con otros datos de la conexión, tal
como el nombre del usuario, su contraseña, nombre del controlador ODBC a usar, el nombre
de la base de datos, el servidor donde se ubica esta base de datos, nombre de la estación de
trabajo desde la que vamos a trabajar e incluso el nombre de la aplicación en la que vamos a
usar los datos de esa base. Esta propiedad es mucho más completa que la anterior, pero un
poco más complicada de usar.

Para introducir los datos de la propiedad Connect deberá usar una palabra para definir el dato,
seguido del signo = y del dato a introducir. Como final del dato debe introducir necesariamente
el signo punto y coma ;

DSN Origen de datos ODBC registrado. DSN=MiConexiónODBC;


UID Nombre de un usuario reconocido UID=Luis;
PWD Contraseña asociada al usuario PWD=MiContraseña;
DRIVER Descripción del controlador DRIVER=SQL Server;
DATABASE Base de datos predeterminada
para usarla una vez conectado DATABASE=MiBase;
SERVER Nombre del servidor donde se
aloja la base de datos SERVER=MiServidor;

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 15


WSID Nombre de la estación de trabajo
(Nombre del PC que se va a
comunicar con el servidor WSID=NombredemiPC;
APP Nombre de la Aplicación que va a
Usar la Base de Datos APP=MiAplicación

NOTA - Si conoce SQLServer, DATABASE es el nombre de la base de datos que quiere utilizar
una vez realizada la conexión. Para los que no conocen SQLServer, dentro de un fichero de
esta base de datos pueden existir varias bases de datos. Y cada una de ellas puede tener
varias tablas. Es decir, la configuración de esta BD no es tan simple como la de Access. Cada
una de estas bases de datos tiene un propietario y varios usuarios. Cada usuario tiene
habilitadas unas funciones (p.e. un usuario puede leer y escribir y otro solamente leer) Este
parámetro le indica cual de esas bases de datos que contiene el fichero de SQLServer (para
hablar con mas propiedad, el sistema de ficheros de SQLServer)

SQLServer mostrando su carpeta de Bases de Datos (BDGepa, master, model, …)

Observe que tras cada parámetro existe un separador ; No es necesario introducir todos los
datos. Dependerá del driver, de cómo haya creado la base de datos, los atributos que le dio a
cada uno de los usuarios. Y como no, dependerá del tipo de base de datos que esté usando
(SQLServer, Oracle, etc.). Recuerde lo mencionado más atrás. No se fíe nunca de que su
aplicación trabaja perfectamente sobre una base de datos. Lo más probable es que si cambia
de BD ya no le trabajará tan perfectamente.

Veamos un ejemplo de cómo introducir esta propiedad:

Dim MiVariable As String


MiVariable = "DSN=MiConexionODBC;UID=Luis;PWD=MiContraseña;DATABASE=BaseGE;"
RemoteData1.Connect = MiVariable

El hecho de que podamos abrir una base de datos mediante DatasourceName o Connect
tiene su explicación. Si tenemos creada una conexión ODBC con todos los datos necesarios
para que pueda abrir una base de datos, es mucho más simple usar la propiedad
DatasourceName y el Control RemoteData le abrirá perfectamente la BD. Pero cuando

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 16


usamos una BD a través de Red de Area Local, lo normal es que esa base esté compartida por
varios usuarios, que cada uno tendrá un nombre y un Password, que puede estar habilitado
para trabajar desde un puesto o desde varios puestos, e incluso puede estar habilitado para
trabajar sobre una BD utilizando una determinada aplicación, y no estarlo para utilizar esa
misma BD con una aplicación distinta. Por eso este control nos brinda las dos posibilidades,
una sencilla, DatasourceName, para trabajar con los datos ya introducidos en la conexión
ODBC, y la otra, para variar los datos de esa conexión ODBC ya existente y lograr con ello
todas las ventajas que nos ofrece ODBC respecto a restricciones de usuarios, contraseñas,
etc. (la conexión ODBC en este caso es muy normal que tenga solamente el nombre, y que no
apunte a ninguna base de datos concreta). Puede incluso utilizar ambas propiedades. Es muy
típico por ejemplo, que la conexión apunte a una determinada base de datos, (el nombre de la
conexión se lo pasamos en la propiedad DatasourceName) y que en la propiedad Connect le
pasamos el nombre del usuario y la contraseña.

Puede utilizar el control, RemoteData incluso sin tener una conexión preestablecida. Pero
deberá establecer mediante el programa, utilizando los métodos OpenConnection o
EstablishConnection. Se sale del contenido deseado para este curso comentar estos
métodos, pero el alumno aventajado puede intentar obtener información en la escasa
bibliografía existente. No le recomiendo que se complique la vida rizando el rizo, pudiendo
establecer previamente la conexión ODBC.

Propiedad SQL
Mediante las dos propiedades estudiadas, DatasourceName y Connect hacemos que el
control RemoteData sepa la conexión sobre la que va a trabajar - y por lo tanto la base de
datos que utilizará. Ahora nos falta indicarle los datos que deseamos leer o escribir. Nos falta
lo que sería en DAO, darle los datos para crear el Recordset (Por ejemplo el nombre de una
tabla o una sentencia SQL, tal como hacíamos en la propiedad RecordSource del control
Data). Para el control RemoteData esta información se le introduce en la propiedad SQL

La propiedad SQL establece o devuelve una instrucción SQL válida para crear un conjunto de
registros a partir del origen de datos establecido en las propiedades DatasourceName o
Connect. Esta instrucción SQL debe comenzar necesariamente por SELECT, En tiempo de
ejecución, podemos asignar a esta propiedad el nombre de una Consulta ya almacenada en la
BD, pero en este caso, debemos anteponer la palabra EXECUTE. También podemos introducir
en esta propiedad un rdoQuery, un rdoResultset o un rdoTable. Eso lo veremos más
adelante.

Para establecer esta propiedad en tiempo de diseño, basta con escribir la instrucción SQL en
la ventana de propiedades. Una instrucción típica sería

SELECT * From Alumnos


SELECT * From Alumnos Where Apellido1= 'Suárez'

En tiempo de ejecución podemos introducir una de estas instrucciones en la propiedad SQL

MSRDC1.SQL = "SELECT * From Alumnos Where Apellido1= 'Suárez'"

Si la BD tiene una consulta (la típica consulta de Access) llamada C_Suarez, donde hemos
seleccionado todos los registros cuyo campo Apellido1 sea Suárez, podemos poner:

MSRDC1.SQL = EXECUTE C_Suarez

(No intente hacer esto mismo con el nombre de una tabla. Solamente sirve para consultas)

Con los registros seleccionados por la propiedad SQL, formamos lo que en DAO era un
recordset, pero en este caso adopta otro nombre: rdoResultset. En RDO se ha buscado otra
terminología, posiblemente para diferenciarlo claramente de DAO. Por ejemplo, en vez de
registros es habitual hablar de Filas, y en vez de campos, hablamos de Columnas.

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 17


Si pudiésemos crear un rdoResultset mediante algún procedimiento, (y seguro que podremos
hacerlo), podemos introducir directamente ese rdoResultset como rdoResultset del control
RemoteData, al igual que lo hacíamos con el Recordset del Control Data en DAO:

Set MSRDC1.Resultset = rdoResultsetYaCreado

Propiedad Connection
Veamos previamente que es un objeto rdoConnection. Un Objeto rdoConnection es un objeto
de acceso a datos remotos. Es el equivalente al objeto Database en DAO (Vea cuadro página
2) El control RemoteData tiene un objeto rdoConnection subyacente y podemos "verlo"
mediante esta propiedad. El poner verlo entre comillas no significa otra cosa que, al igual que
ocurría con el objeto Database, el objeto rdoConnection es un objeto de acceso a datos del
que podemos ver sus propiedades y ejecutar sus métodos. Por ejemplo, si queremos ver la
cadena de conexión completa podemos analizar la propiedad Connect del Objeto Connection:

Label1 = MSRDC1.Connection.Connect

Si deseamos saber si el control RemoteData sigue conectado para realizar una determinada
operación:
If MSRDC1.Connection.StillConnecting Then ….

Podemos ejecutar uno de sus métodos. Por ejemplo, cerrar la conexión

MSRDC1.Connection.Close

Propiedades EOFAction y BOFAction


Establecen el comportamiento del RemoteData cuando llega a la fila anterior a la primera o a
la fila posterior a la última. (Y no es un juego de palabras) Puede establecerse en tiempo de
diseño, mediante la caja de propiedades, o en tiempo de ejecución mediante la siguiente
sintaxis:

MSRDC1.BOFAction = valor
MSRDC1.EOFAction = valor
Los valores (o constantes) que puede tomar son los siguientes:

Para la propiedad BOFAction

Valor Constante Efecto

0 rdMoveFirst Se mueve a la primera fila


1 rdBOF Se mantiene en la fila anterior a la primera. Se genera el evento
Validate y a continuación el evento Reposition, y se desactiva el
botón de desplazar hacia abajo

Para la propiedad EOFAction

Valor Constante Efecto


0 rdMoveLast Se mueve a la última fila
1 rdEOF Se queda en la fila posterior a la última. Se genera el evento Validate
y a continuación el evento Reposition. Se desactiva el botón de
desplazar hacia arriba.
2 rdAddNew Crea una nueva fila.

La propiedad EOFAction sólo tiene efecto cuando se manipula el cambio de filas mediante el
ratón, sobre los botones del control RemoteData. No tiene efecto si se llega a la fila posterior a
la última mediante código. (Por ejemplo, mediante la instrucción MSRDC1.resultset.MoveNext)

NO es recomendable establecer la propiedad BOFAction a 1 (rdBOF) ni la propiedad


EOFAction a 1 (rdEOF), ya que puede entrar en una situación de la que es imposible salir. Si

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 18


ve aparecer un aviso de error parecido a Estado del conjunto de datos no válido para Update le
está indicando que se ha metido en un proceso del que no puede salir, debido a que se
encuentra en el EOF ó BOF intentando introducir un nuevo dato, y no puede.

Propiedad CursorDriver
Devuelve o establece un valor que especifica el tipo de cursor que se va a crear. Veamos
primero qué es un cursor. Según la definición de Microsoft:

Conjunto lógico de filas administrado por el origen de datos o por el administrador de


controladores ODBC. Los cursores reciben dicho nombre porque indican la posición actual
dentro del conjunto de resultados, igual que el cursor de la pantalla indica la posición actual.
(#G!*¡&@%)

Vamos a no complicarnos la vida para intentar comprenderlo. El mecanismo de ODBC espera


una base de datos albergada en un servidor, a la que le vamos a manipular sus registros desde
un puesto conectado al servidor donde se encuentra la base de datos a través de una red de
área local. Cuando creamos un recordset, el conjunto de registros que forma ese recordset
deberá estar en la memoria RAM de algún equipo. ¿Del servidor? ¿Del cliente? En cualquiera
de ellos que esté deberá estar en la memoria RAM, ocupando cierto espacio. A esa memoria
ocupada por el recordset, y a la forma en la que están guardados los datos dentro de ella es a
lo que llamamos Cursor. Este concepto de cursores es nuevo (No existía en DAO) debido a
que RDO se utiliza fundamentalmente en sistemas basados en un servidor, donde se alberga
la base de datos, y una serie de puestos de operación, unidos al servidor a través de una red.
El tráfico de datos a través de la red es algo que se debe optimizar. Y en algunos casos puede
ser beneficioso llevarse todas las filas de un rdoResultset al puesto, operar con ellas e
introducirlas de nuevo, si es necesario, en la base de datos, una vez procesadas, o puede ser
beneficioso mantener ese conjunto de filas en la memoria RAM del servidor para tener
disponibles allí los datos y acceder a ellos de forma rápida a través de la red. En un caso
lograremos o rapidez y en otro poco tráfico, pero en ambos casos gastaremos recursos.
Podemos no crear un cursor, no usaremos memoria pero, o empleamos mas tiempo, o
introducimos más tráfico en la red.

El crear un cursor de lado cliente o de lado servidor puede hacer que su código funciones o
no funcione. Los cursores lado cliente suelen ser de lectura / escritura, que permiten avanzar
hacia a delante y hacia atrás. Los cursores lado servidor suelen ser solamente de lectura y
de avance solamente hacia delante. Hemos empleado una palabra no muy exacta: suelen
ser. Y es que eso dependerá de la base de datos (Oracle no se comporta como SQLServer,
y ninguna de ellas se comporta como Access) y depende también del controlador ODBC que
utilice (Hay controladores de varias marcas para la misma base de datos) Es muy frecuente
realizar un código que funciona perfectamente con un controlador ODBC, y cuando se
cambia de controlador – o de versión – ya no funciona. Le recomiendo mucho cuidado.

El control RemoteData permite elegir el crear un cursor en el servidor, en el puesto, o crearlo


solamente si es necesario. Para ello usamos la propiedad CursorDriver. Puede tomar los
siguientes valores:

Constante Valor Descripción


El controlador ODBC elegirá el tipo de cursores adecuado. Se
rdUseIfNeeded 0
usarán cursores del servidor si hay alguno disponible.
rdUseOdbc 1 RemoteData usará la biblioteca de cursores de ODBC .
rdUseServer 2 Se usarán cursores del lado del servidor.
rdUseClientBatch 3 RDO usará la biblioteca de cursores por lotes de tipo optimista.
Le recomiendo que repase el tema de cursores de la base de datos concreta que esté usando,
y espero que la bibliografía que le brinda el fabricante sea suficiente. No suelen ser muy
explícitos con los manuales aportados, o al menos tienen la habilidad de explicarlo de una
forma tan sutil que es a veces inescrutable. Casi siempre esas dudas se resuelven en el curso
que cada marca tienen para su base de datos, que es estrictamente de pago.

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 19


Métodos del control RemoteData

Método UpdateRow
Es equivalente al método UpdateRecord del Control Data. Guarda los valores actuales de los
controles enlazados en la base de datos. El método UpdateRow tiene el mismo efecto que
ejecutar el método Edit, modificar una columna y después ejecutar el método Update, excepto
que no ocurre ningún evento.

Nota Cuando usa una biblioteca de cursores ClientBatch, todas las actualizaciones a las tablas
base se retrasan hasta que use el método BatchUpdate. En este caso, el método UpdateRow
actualiza el rdoResultset local, pero no actualiza las tablas base. Estos cambios pueden
perderse si la aplicación termina antes de que se haya completado el método BatchUpdate.

Método BatchUpdate (Método del rdoResultset)


Este método no es del control RemoteData, sino de su rdoResultset asociado.

De igual forma que un control data tenía asociado un recordset, un RemoteData tiene asociado
un Resultset. El Resultset es el objeto rdoResultset del control RemoteData (Colección de
registros, o si lo prefiere, de filas ya que estamos en RDO), y que como cualquier objeto de
acceso a datos, tiene sus métodos, y este es uno.

Realiza una actualización optimista por lotes.

Sintaxis MSRDC1.Resultset.BatchUpdate (filaunica, forzar)

Donde MSRDC1 es el nombre del control RemoteData


Filaunica (Booleano) indica si es True, que solamente actualizará la fila actual, si es False,
actualiza todo el lote. El lote es un conjunto de filas. Pueden ser las filas del cursor.
Forzar (Booleano)indica si está a True que sobreescribirá la fila actual, independientemente de
si causa o no colisiones. Si está a False, no sobreescribirá si va a ocurrir una colisión.

Este método es un método del rdoResultset. Si tenemos un rdoResultset creado con código
(Ahora veremos como se hace) la sintaxis sería

MirdoResultset. BatchUpdate (filaunica, forzar)

Con esta introducción ya podemos pensar que el alumno tiene cierta idea respecto a lo que es
el control RemoteData. Vamos a comenzar a explicar lo que son los objetos de acceso remoto
a datos (Objetos RDO) y podremos seguir viendo cosas acerca del control RemoteData como
aplicación de estos nuevos objetos.

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 20


Objetos de datos remotos (Objetos RDO)

Como ya conocemos los objetos de acceso a datos DAO, veremos los objetos RDO
basándonos un poco en este conocimiento.

Los objetos de datos remotos nos permiten manipular componentes de un sistema de base de
datos ODBC remoto. Lo de remoto no implica que la base de datos deba estar en un
ordenador distinto al que tiene la aplicación. (Aunque esta sea la disposición más usual en
aplicaciones que usan RDO). El significado de RDO es que se accede a la base de datos a
través de una conexión ODBC.

RDO solamente funciona en plataformas de 32 bits. (Windows 95/98/2000 o Windows NT).


Para usar objetos de datos remotos, debe establecer una referencia a Microsoft Remote Data
Object 2.0 en Proyecto | Referencias.

Al igual que en DAO, los objetos RDO tienen una estructura jerárquica que se puede ver en la
siguiente figura:

Estructura jerárquica de los objetos RDO

Los objetos RDO siguen la misma regla para su creación que los objetos DAO: el objeto
jerárquicamente superior crea al objeto inferior.

El Objeto rdoEngine
El objeto rdoEngine representa el origen de datos remoto. Es el equivalente al dbEngine de
DAO, es decir, el motor de bases de datos. Es el objeto de nivel jerárquico superior, por lo
tanto no se crea por otro objeto, sino que está creado simplemente al introducir la referencia.

La característica del rdoEngine es que trabaja siempre a través del Administrador de


controladores. El objeto rdoEngine contiene al objeto rdoEnvironments (Colección de
objetos rdoEnvironment) y el rdoErrors.

Los objetos rdoEnvironment de nueva creación se inicializan de acuerdo a los valores


predeterminados establecidos en el objeto rdoEngine. Se crea de forma automática el objeto
rdoEnvironments(0), al igual que lo hacía el dbEngine con el Workspaces(0) en DAO.

El objeto rdoErrors contiene todos los mensajes de error enviados desde el origen de datos
remoto. Cada vez que se recibe uno de estos mensajes, se produce el evento InfoMessage del
rdoEngine

Propiedades del objeto rdoEngine

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 21


rdoDefaultLoginTimeout Determina el valor predeterminado la propiedad
LoginTimeout de los objetos rdoEnvironment que se creen. Esta propiedad se utiliza en la
administración del tiempo disponible para la conexión. Si la conexión no se ha realizado en el
número de segundos indicado, dará error.
Sintaxis rdoEngine.rdoDefaultLoginTimeout = NumeroDeSegundos

Si el valor NumeroDeSegundos es cero, esperará indefinidamente a que se realice la


conexión.

rdoDefaultCursorDriver Determina el valor predeterminado de la propiedad


CursorDriver de los objetos rdoEnvironment. Esta propiedad determina si el Administrador
de controladores ODBC crea cursores por lotes del lado del cliente, locales, del servidor o si no
crea cursores.

Sintaxis rdoEngine.rdoDefaultCursorDriver = valor

Donde Valor es un valor o contante según puede verse en la siguiente tabla


RdUseIfNeeded (Predeterminado) elige el estilo de cursores más apropiado para el
Controlador
RdUseODBC Utiliza la biblioteca de cursores ODBC.
RdUseServer Utiliza cursores del servidor
RdUseClientBatch Usa la biblioteca de cursores optimista por lotes
RdUseNone No crea un cursor desplazable. Básicamente es un conjunto de
resultados de sólo lectura de tipo forward-only

rdoDefaultUser y rdoDefaultPassword Determinan los valores predeterminados de


las propiedades UserName y Password de los objetos rdoEnvironment cuando se abren
conexiones sin suministrar valores para estos parámetros.

rdoVersion Examina la versión de RDO en uso.

rdoLocaleID Devuelve o establece un valor que indica la configuración regional de la


biblioteca RDO, para mostrar los mensajes de error.
Sintaxis rdoEngine.rdoLocaleID = valor

Por defecto, esta propiedad toma el valor 0, que pone la configuración establecida en
Windows.
Si el archivo DLL del idioma especificado no está presente en el equipo del usuario, RDO se
establece como rdLocaleEnglish, lo cual no requiere un archivo DLL independiente. Cuando
esto ocurre, se coloca un mensaje informativo en la colección rdoErrors para indicar que RDO
no pudo cargar el archivo DLL de recursos para la configuración regional especificada.
Cuando distribuya la aplicación, asegúrese de incluir el archivo DLL del lenguaje apropiado.

Métodos del rdoEngine


rdoCreateEnvironment Este método es equivalente al CreateWorkspace de DAO. Crea
un nuevo objeto rdoEnvironment. (Es decir, una sesión de trabajo)
Sintaxis Set MiSesion = rdoEngine.rdoCreateEnvironment(Nombre, Usuario,
Contraseña)

Donde:
Nombre es la propiedad Name del nuevo objeto rdoEnvironment. (En el código, para nombrar
a este rdoEnvironment debemos hacerlo con MiSesion). Debe suministrar un nombre, ya que
si no lo hace, este rdoEnvironment creado no se suma a la colección rdoEnvironments.
Usuario es el nombre del usuario.
Contraseña es la contraseña usada en esa sesión. Puede tener hasta 14 caracteres.

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 22


Cuando se inicializa el rdoEngine se crea automáticamente una sesión de trabajo
predeterminada, el rdoEnvironments(0), con el nombre de usuario que tenga el rdoEngine en
su propiedad rdoDefaultUser y con contraseña igual a la propiedad rdoDefaultPassword. En
una aplicación multiusuario es necesario crear un rdoEnvironment para cada uno de ellos,
siempre que empleemos transacciones. En este método es necesario suministrar todos los
parámetros (Nombre, Usuario y Contraseña)
rdoRegisterDataSource Introduce la información de conexión en el Registro de
Windows para un origen de datos ODBC (Crea una conexión ODBC igual que lo haríamos en
Windows)
Sintaxis rdoEngine.rdoRegisterDataSource DSN, controlador, silencio,
atributos

DSN es el nombre que queremos dar a la conexión ODBC


Controlador es el nombre del controlador ODBC. Debe ser uno de los instalados y hay que
poner el nombre exacto por el que se le conoce en Windows, NO el nombre de la DLL. Por
ejemplo, debe poner Microsoft Access Driver y no odbcjt32.dll
Silencio es un valor True / False y se refiere a si queremos que presente el cuadro de
creación de un enlace ODBC (El mismo que aparece en Windows) Si ponemos False en esta
propiedad, le introducimos los datos de la conexión a través de ese cuadro. Si le ponemos
True, no mostrará el cuadro, y por lo tanto deberemos pasarle todos los parámetros
correctamente. Si la información suministrada no es completa, mostrará el cuadro citado.
Atributos. Una expresión de cadena que es una lista de palabras clave que se van a agregar
al archivo ODBC.INI. Las palabras claves están en una cadena delimitadas por retornos de
carro. No es trivial esta cadena de caracteres y es propia de cada controlador. Por lo tanto, le
recomiendo que si no conoce muy bien la cadena a introducir, ponga el parámetro Silencio a
False y se olvide de este parámetro de atributos. Eso sí, deberá ser el usuario quien introduzca
los datos a través del cuadro de creación del enlace ODBC.

Hasta aquí las propiedades y métodos del rdoEngine. Vamos a bajar un nivel jerárquico y ver
el siguiente objeto RDO

El Objeto rdoEnvironment
Un objeto rdoEnvironment es una sesión de trabajo en RDO. Equivale al Workspace de
DAO. En un rdoEnvironment podemos tener varios objetos Connection (varias conexiones)
de la misma forma que en un Workspace podíamos tener varias objetos Database.

La colección de todos los objetos rdoEnvironment es el objeto rdoEnvironments. Visual


Basic crea automáticamente un rdoEnvironment, de la misma forma que creaba un
Workspace. El objeto rdoEnvironment creado es el rdoEnvironments(0) y el nombre de
usuario será el que tenga el rdoEngine en su propiedad rdoDefaultUser y la contraseña igual
a la propiedad rdoDefaultPassword

NOTA. Visual Basic crea automáticamente un Workspace o un rdoEnvironment si el


proyecto contiene la referencia al motor de bases de datos correspondiente. Visual Basic no
creará ninguno de ellos si no tiene la referencia a ningún motor de bases de datos.

Los objetos rdoEnvironment se anexan automáticamente a la colección rdoEnvironments a


menos que no proporcione un nombre para el nuevo objeto cuando utilice el método
rdoCreateEnvironment.

Propiedades del Objeto rdoEnvironment


Propiedad CursorDriver Ya hemos visto esta propiedad para el control RemoteData. La
aplicación al objeto rdoEnvironment es similar, por lo que solamente exponemos su sintaxis:

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 23


MiSesión.CursorDriver = Valor donde Valor toma uno de estos valores o constantes:

0 rdUseIfNeeded El controlador ODBC elegirá el tipo de cursores


adecuado. Se
usarán cursores del servidor si hay alguno disponible.
1 rdUseOdbc Usará la biblioteca de cursores de ODBC .
2 rdUseServer Se usarán cursores del lado del servidor.
3 rdUseClientBatch RDO usará la biblioteca de cursores por lotes de tipo optimista.

Propiedad hEnv
Esta propiedad es el Handle de la conexión ODBC. Es similar a la propiedad hDC (para
controles) o hWnd (para formularios) que ya hemos visto en capítulos anteriores. Esta
propiedad es sólo de lectura y devuelve un Long. Este valor lo usan las APIs de Windows para
trabajar. Alguna instrucción nos pedirá el hEnv como parámetro.

Propiedad LoginTimeout
Devuelve o establece el número de segundos que el Administrador de controladores ODBC
espera antes de que se produzca un error de espera al abrir una conexión.

Sintaxis NombreDelObjetordoEnvironment.LoginTimeout = NumeroDeSegundos

El valor predeterminado es el de la propiedad rdoDefaultLoginTimeout del objeto


rdoEngine, y en su defecto, de 15 segundos. Si este valor es igual a 0 se espera
indefinidamente y no se producirá ningún error.

Si establece un valor para esta misma propiedad en uno de sus objetos rdoConnection, este
valor es prioritario al establecido en el objeto rdoEnvironment.

Métodos del objeto rdoEnvironment

Método OpenConnection
Abre una conexión con un origen de datos ODBC. En otras palabras, crea un objeto
rdoConnection, objeto que deberá declarar antes de abrirlo:

Dim MiConexion as rdoConnection


Set MiConexión = MiSesion.OpenConnection(Nombre, LineaComandos, SóloLectura,
Conectar, Opciones)

Nombre puede ser una conexión ya creada, en cuyo caso se abrirá esa conexión. Si este
parámetro es una cadena vacía, deberá obtener los datos de la conexión, o bien del
argumento Conectar, o mediante el cuadro de dialogo de abrir la conexión.

LineaComandos. Determina si muestra o no muestra el cuadro de diálogo de abrir la


conexión ODBC. Puede tomar estos valores
rdDriverPrompt (0) Muestra el cuadro de diálogo
rdDriverNoPrompt (1) No muestra nunca el Cuadro de diálogo
rdDriverComplete (2) Muestra el cuadro de diálogo solamente si la información
facilitada no es suficiente para abrir la conexión.
RdDriverComplete (3) Igual que rdDriverComplete pero deshabilita las opciones
Required que ya estén bien pasadas en la información facilitada.

SóloLectura Determina si la conexión se abre como sólo lectura o para lectura / escritura. Si
no se especifica nada, se abre para lectura / escritura.

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 24


Conectar Este es el argumento que lleva los datos completos de la conexión. Es similar a la
propiedad Connect del control RemoteData, cuyo contenido repetimos aquí por comodidad.

Para introducir los datos de la propiedad Connect deberá usar una palabra para definir el dato,
seguido del signo = y del dato a introducir. Como final del dato debe introducir necesariamente
el signo punto y coma ;

DSN Origen de datos ODBC registrado. DSN=MiConexiónODBC;


UID Nombre de un usuario reconocido UID=Luis;
PWD Contraseña asociada al usuario PWD=MiContraseña;
DRIVER Descripción del controlador DRIVER=SQL Server;
DATABASE Base de datos predeterminada
para usarla una vez conectado DATABASE=MiBase;
SERVER Nombre del servidor donde se
aloja la base de datos SERVER=MiServidor;
WSID Nombre de la estación de trabajo
(Nombre del PC que se va a
comunicar con el servidor WSID=NombredemiPC;
APP Nombre de la Aplicación que va a
Usar la Base de Datos APP=MiAplicación

Estos datos complementan la información de la conexión. Si ya habíamos establecido la


conexión mediante el argumento Nombre, y en esa conexión ya estaban perfectamente
definidos todos los parámetros de esa conexión, de este argumento Conectar solamente
tomará el nombre de usuario y la contraseña.

Puede comprobar si se ha completado la conexión examinando la propiedad StillConnecting


del objeto rdoConnection recién creado, que debe devolver False cuando se ha completado
la operación de conexión.

If MiConexion.StillConnecting = false then ….

BeginTrans, CommitTrans, RollbackTrans (Transacciones)


Son los métodos para realizar transacciones.
• BeginTrans comienza una nueva transacción.
• CommitTrans finaliza la transacción actual y guarda los cambios.
• RollbackTrans finaliza la transacción actual y restaura las bases de datos del objeto
rdoEnvironment al estado en que estaban cuando comenzó la transacción actual.

El funcionamiento en RDO es distinto al de DAO. Además, es distinto para cada base de


datos. La forma de trabajar de SQLServer es distinta de cómo lo hace Oracle. Y muy distinta
de cómo lo hace Access. Le recomiendo que estudie las transacciones en el manual de su
gestor de base de datos.
Hay algunas bases de datos que no aceptan transacciones. Puede comprobarlo analizando la
propiedad Transactions del objeto Connection.

Método Close
Cierra un el rdoEnvironment y todas las conexiones que tenía abiertas. Las modificaciones
pendientes de los objetos RDO inferiores que estuviesen abiertos se deshacen.

Sintaxis MiSesion.Close

No se puede cerrar el rdoEnvironments(0) Si utiliza Close con el objeto ya cerrado, se


producirá un error interceptable..

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 25


El objeto rdoConnection
Un objeto rdoConnection representa una conexión abierta con un origen de datos a través de
ODBC. Es el equivalente al Objeto DataBase de DAO

Un objeto rdoConnection (es decir, una conexión a una base de datos a trvés de ODBC) se
crea o con un control RemoteData o mediante el método OpenConnection del objeto
rdoEnvironment.

Puede también crear un nuevo objeto rdoConnection que no esté vinculado de forma
inmediata con una conexión física específica a un origen de datos. Por ejemplo, el siguiente
código crea un objeto rdoConnection independiente:

Dim OtraConexion as New rdoConnection.

Posteriormente puede introducir las características que desee y establecer la conexión real con
la base de datos. No es normal hacer esto, por lo que le remito en caso necesario, a la ayuda
de VB de este objeto.

Propiedades del Objeto rdoConnection


Un objeto rdoConnection tiene Propiedades. Muchas de ellas ya se han visto, bien al estudiar
el control RemoteData o los objetos RDO ya estudiados. Las propiedades que se han visto se
describirán sólo de forma somera.

Propiedad Connect Devuelve o establece un valor que proporciona información sobre el


origen de un objeto rdoConnection abierto. La propiedad Connect contiene la cadena de
conexión ODBC. Esta propiedad puede leerse siempre, pero no puede modificarse una vez
establecida la conexión.

Sintaxis objeto.Connect = CadenaDeConexión

Las partes de CadenaDeConexión son: (Puede no usar alguna de ellas)

DSN Nombre del origen de datos (Nombre de la conexión ODBC)


UID Nombre del usuario (Puede no tener nombre de Usuario)
PWD Password. (Puede no tener Password)
DRIVER Nombre del driver ODBC empleado
DATABASE Nombre de la base de datos que se va a emplear
SERVER Nombre del servidor remoto
WSIS Nombre de la estación de trabajo dentro de la red
APP Nombre de la Aplicación

(El separador es el carácter punto y coma (;)

No es necesario aportar estos datos para crear la conexión, ya que son los que se han
introducido en Windows al crear la conexión ODBC. Estos datos solamente son necesarios si
la conexión ODBC se creó sin aportarle datos acerca de la base de datos.
Propiedad hDbc
Devuelve el controlador de conexión ODBC.

Sintaxis MiConexion.hDbc

La propiedad hDbc devuelve un valor de tipo Long. Este valor lo utilizan las APIs de Windows.
Y es similar a hDc o hWnd

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 26


Propiedad LastQueryResults
Devuelve un objeto rdoResultset, precisamente el que se ha generado la última consulta, si la
ha habido. Esta propiedad podemos utilizarla para crear un nuevo Resultset, clónico del ultimo
que se ha generado.

Sintaxis
Dim MiRs as rdoResultset
Set MiRs = MiConexion.LastQueryResults

Si no se había creado todavía ningún Resultset, devuelve Nothing.

Propiedad QueryTimeout
Devuelve o establece un valor que especifica el número de segundos que espera el
Administrador de controladores ODBC antes de que se produzca un error de tiempo de espera
al ejecutarse una consulta. El valor predeterminado es de 30 segundos.

Propiedad StillConnecting
Devuelve un valor que indica si la conexión se está estableciendo todavía.

Sintaxis MiConexion.StillConnecting
Esta propiedad devuelve True si la conexión no ha terminado de establecerse, y False si ya
está establecida. Es fundamental saber que la conexión ya está establecida antes de realizar
ninguna operación con ella, por ejemplo, crear un Resultset

Propiedad StillExecuting
Devuelve un valor que indica si una consulta está aún ejecutándose. Esta propiedad se usa
cuando creamos un rdoResultset o un rdoQuery, para conocer si ya se ha finalizado el proceso
de selección de filas que esa operación implica. Esta propiedad puede aplicarse al
rdoConnection, rdoQuery y rdoResultset. Devuelve True cuando la consulta está ejecutándose
todavía, False si ya se ha finalizado.

Sintaxis objeto.StillExecuting

Propiedad Transactions
Devuelve un valor que indica si se pueden realizar transacciones con un objeto rdoConnection
ó rdoResultset. Esta propiedad le permite asegurarse de esta circunstancia antes de ejecutar la
instrucción BeginTrans.
La propiedad Transactions llama a la función SQLGetInfo de ODBC para determinar si el
controlador ODBC es capaz de permitir transacciones, no si el conjunto de resultados actual es
actualizable.

Propiedad AsyncCheckInterval
Devuelve o establece un valor que especifica el número de milisegundos que espera RDO
entre dos comprobaciones para ver si se ha completado una consulta asíncrona.

Sintaxis MiConexion.AsyncCheckInterval = valor

El valor por defecto es de 1 segundo (1000 mseg)

Comentarios Al usar la opción rdAsyncEnable para ejecutar una consulta de forma


asíncrona, RDO comprueba periódicamente el origen de datos para determinar si la consulta
se ha completado. Puede modificar la duración del intervalo entre comprobaciones mediante

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 27


la propiedad AsyncCheckInterval. RDO también comprueba el estado de las consultas
asíncronas cuando se examina la propiedad StillExecuting.

Propiedad UpdateOperation
Esta propiedad afecta a la forma en la que se realiza la modificación de una fila en una
actualización optimista por lotes. Si a esta propiedad se le pone el valor 0 (Predeterminado) la
modificación de la fila se realiza mediante una instrucción Update. Si el valor es 1, la
operación de modificación se realiza mediante dos instrucciones, primero una instrucción
Delete (borra la fila) y a continuación otra instrucción Insert (Crea la fila con los nuevos
valores).

Sintaxis objeto.UpdateOperation [= valor]

El Objeto rdoResultset
El Objeto rdoResultset es el conjunto de filas que devuelve la ejecución de una consulta. Es

el equivalente al Recordset de DAO

El Objeto rdoResultset se crea mediante el método OpenResultset del rdoConnection.

Ejemplo:
‘Creamos el objeto rdoEnvironment utilizando el objeto creado automáticamente por VB
Set GepaWs = rdoEnvironments(0)
‘El objeto rdoEnvironment crea el objeto rdoConnection
Set GepaConex = GepaWs.OpenConnection(“Gepa”, rdDriverNoPrompt, False)
‘(Gepa es el nombre de la conexión ODBC creada en el ordenador)
‘El objeto rdoConnection crea el objeto rdoResultset

Set GepaRs = GepaConex.OpenResultset("Select Ex_expedite, Ex_numproye, " & _


"Ex_presenta, Ex_plan, Ex_tipoexpe, Ex_tipoprop, Ex_tipotram, Ex_redaproy, Ex_situxpe, " &
_
"Ex_Numero_Ini, Ex_subsiste " & _
"From Expedientes Order By Ex_Numero_Ini", rdOpenDynamic, rdConcurRowVer)

Puede ver que el proceso de creación de un rdoResultset en RDO no difiere demasiado de la


creación de un recordset en DAO.

Veamos cada una de las partes del Método OpenResultset

Set MirdoResultset = MiConexión.OpenResultset(nombre [,tipo [,tipoBloq


[,opciones]]])

Donde
MirdoResultset = variable tipo rdoResultset que debe estar declarada.
MiConexión = Objeto Connection con el que se crea el rdoRsultset
Nombre = Nombre de una tabla o consulta de la base de datos, o una sentencia
SQL que pueda devolver filas.
Tipo = Tipo de cursor que se va a crear
TipoBloq = Tipo de bloqueo de la base de datos. Por defecto, lo crea solo lectura.
Opciones = Opciones que puede tener el rdoResultset

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 28


El argumento Tipo puede tener una de estos valores:

Constante Valor Descripción


rdOpenForwardOnly 0 (Predeterminado) Abre un rdoResultset tipo forward-only.
rdOpenKeyset 1 Abre un rdoResultset tipo Keyset
rdOpenDynamic 2 Abre un rdoResultset tipo Dinamico
rdOpenStatic 3 Abre un rdoResultset tipo estático

El tipo forwar-only es un rdoResultset en el que las filas solamente se pueden explorar en


sentido ascendente. No se puede retroceder .
El tipo Keyset es un rdoResultset que se puede actualizar, insertar nuevas filas, y se puede
recorrer en ambos sentidos sin limitación. Los miembros de este rdoResultset son fijos.
El tipo Dinámico es un rdoResultset que se puede actualizar, insertar nuevas filas, y se puede
recorrer en ambos sentidos sin limitación. Los miembros de este rdoResultset no son fijos.Es
similar al Dynaset de DAO.
El tipo estático presenta los valores existentes en la BD en el momento de su creación y no
detecta las posibles variaciones de los datos en la misma. Es similar al Snapshot de DAO

Para el parámetro Tipo de Bloqueo acepta los siguientes datos:

Constante Valor Descripción


rdConcurReadOnly 1 (Predeterminado) Sólo lectura.
RdConcurLock 2 Concurrencia pesimista.
rdConcurRowVer 3 Concurrencia optimista basada en el Id. de fila.
rdConcurValues 4 Concurrencia optimista basada en valores de filas.
rdConcurBatch 5 Concurrencia optimista usando actualizaciones de modo por
lotes. Valores Status devueltos por cada fila actualizada con
éxito.

El parámetro opciones acepta estos valores: (Se pueden sumar ambas)

Constante Valor Descripción


rdAsyncEnable 32 Ejecuta la operación de forma asíncrona.
rdExecDirect 64 (Predeterminado) Evita la creación de procedimientos
almacenados para ejecutar la consulta.

El objeto rdoResultset tiene algunas particularidades que no tienen los recordsets de DAO, por
ejemplo, poder obtener resultados múltiples, es decir, se pueden introducir varias sentencias
SELECT y cada una de ellas crea un conjunto de registros. Esto no significa que haya mas de
un rdoResultset, sino que existe un único rdoResultset con resultados múltiples. Se puede ir
accediendo a cada uno de los conjuntos de registros mediante el método MoreResults.

Propiedades del Objeto rdoResultset


El rdoResultset no tiene exactamente las mismas propiedades que el Recordset. Y además no
siempre funcionan tal como lo hacían en el recordset. En RDO van a depender del tipo de
cursor y del tipo de bloqueo. Veamos las propiedades del rdoResultset

AbsolutePosition. Igual que en RDO, pero no siempre funciona, ya que depende del tipo de
cursor.

ActiveConnection Devuelve una referencia a la conexión con la que está asociado el


rdoResultset

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 29


BatchCollisionCount Devuelve un valor que especifica el número de filas que no finalizaron
la última actualización por lotes. Devuelve un Long. En caso de que esta propiedad sea mayor
de 0 significa que la actualización por lotes no se ha completado con éxito. En este caso habrá
que ejecutar el método BatchUpdate para completar la actualización.

BatchCollisionRows
Devuelve una matriz de marcadores que indica las filas que han provocado colisiones en la
última operación de actualización por lotes. Devuelve un Variant con una matriz de las filas
que han provocado una colisión la última vez que se invocó el método BatchUpdate. El
número de elementos de esta matriz es el que indica la propiedad BatchCollisionCount

BatchSize (Propiedad)
Devuelve o establece un valor que especifica el número de instrucciones enviadas al servidor
en cada lote. De forma predeterminada se envían 15 instrucciones al servidor en cada lote.
Esta propiedad puede modificarse en cualquier momento. Si un DBMS no admite lotes de
instrucciones, puede establecer esta propiedad a 1, con lo que cada instrucción se enviará por
separado.

BOF, EOF Son idénticas a las mismas propiedades del Recordset de DAO

Bookmark Funciona igual que en el Recordset de DAO. Pero en RDO es posible que esa
propiedad no se pueda usar. Depende del tipo de cursor. Para asegurarse de que el objeto
rdoResultset admite marcadores, examine el valor de su propiedad Bookmarkable antes de
usar su propiedad Bookmark. Si Bookmarkable es False, el objeto rdoResultset no admite
marcadores y el uso de Bookmark producirá un error
La propiedad Bookmark no se aplica a los objetos rdoResultset de tipo forward-only.

En DAO la variable donde se guarda el Bookmark debía se un String. En RDO es un


variant. Desconozco la razón, pero usando una variable String para almacenar el Bookmark
falla.

Bookmarkable Devuelve un valor que indica si un objeto rdoResultset admite marcadores,


es decir, si acepta la propiedad Bookmark.

EditMode Devuelve un valor que indica el estado de edición de la fila actual. Devuelve un
integer o una constante de acuerdo con la tabla siguiente:

Constante Valor Descripción

RdEditNone 0 No se está efectuando ninguna operación de modificación.


RdEditInProgress 1 Se ha invocado el método Edit y la fila está en buffer de copia.
RdEditInProgress 2 Se ha invocado el método AddNew y la fila actual del búfer de
copia es una fila nueva que no se ha guardado en la B. D.

LastModified Devuelve un marcador que indica la última fila modificada o agregada más
recientemente. Este marcador es el Bookmark de esa fila. Devuelve un Variant.

LockEdits Devuelve un valor de tipo Booleano que indica el tipo de bloqueo en vigor. Si
devuelve True utiliza bloqueo pesimista. Si devuelve False utiliza bloqueo optimista.

Si LockEdits es True y otro usuario ya tiene la página bloqueada, se producirá un


error al intentar usar el método OpenResultset. En general, los demás usuarios pueden
leer datos de las páginas bloqueadas.
Si LockEdits es False (valor predeterminado) y utiliza después Update mientras la
página está bloqueada por otro usuario, se producirá un error.

El bloqueo se realiza sobre una página de datos. La página suele se de 2 K (Ese es el


tamaño que utiliza Microsoft SQL Server)

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 30


LockType Devuelve o establece un valor entero de tipo Long que indica el tipo de tratamiento
de concurrencia. Los valores admitidos son:
Constante Valor Descripción
(Predeterminado) El cursor es de sólo lectura. No se admiten
rdConcurReadOnly 1
actualizaciones.
rdConcurLock 2 Concurrencia pesimista.
rdConcurRowVer 3 Concurrencia optimista basada en el identificador de fila.
rdConcurValues 4 Concurrencia optimista basada en los valores de las filas.
Concurrencia optimista con actualizaciones por lotes. Se obtienen
rdConcurBatch 5
valores de estado para cada fila actualizada correctamente.
Lea la ayuda de VB para obtener mayor información de cada uno de los tipos.
Restartable Devuelve un valor que indica si un objeto rdoResultset admite el método
Requery, que vuelve a ejecutar la consulta en la que está basado el objeto rdoResultset. Debe
usarse antes de utilizar el método Requery para evitar que se produzca un error.

PercentPosition
Devuelve o establece un valor que indica o modifica la ubicación aproximada de la fila actual
en el objeto rdoResultset, basándose en el porcentaje con respecto al total de filas de dicho
objeto. El valor devuelto es un Single entre 0,0 y 100,0

Puede usar la propiedad PercentPosition con una barra de desplazamiento de un control


Form o TextBox para indicar la ubicación de la fila actual en un objeto rdoResultset. Esta
propiedad solamente se aplica a los rdoResultset tipo Keyset y Dynamic.

RowCount Devuelve el número de filas a las que se ha tenido acceso en un objeto


rdoResultset. Es un Long.
Esta propiedad no indica el número de filas del Resultset, sino el número de filas a las que se
ha accedido. No es por lo tanto, el equivalente a la propiedad RecordCount del Recordset
DAO.
Si esta propiedad no está disponible en el controlador, devuelve -1

Status Devuelve o establece el estado de la fila o columna actual. El valor de esta propiedad
indica si la fila o la columna estarán implicadas en la próxima actualización optimista por lotes
y de qué modo lo estarán.

Los valores admitidos para la propiedad Status son:

Constante Valor Valor de la propiedad Prepared


(Predeterminado) La fila o la columna no se han modificado o se
rdRowUnmodified 0
han actualizado correctamente.
La fila o la columna se han modificado y aún no se han
rdRowModified 1
actualizado en la base de datos.
La fila o la columna se han insertado con el método AddNew,
rdRowNew 2
pero aún no se han insertado en la base de datos.
La fila o la columna se han eliminado, pero aún no se han
rdRowDeleted 3
eliminado de la base de datos.
La fila o la columna se han eliminado localmente y también de la
rdRowDBDeleted 4
base de datos.

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 31


StillExecuting Devuelve un valor de tipo Booleano que indica si una consulta está aún
ejecutándose.
Esta propiedad es muy útil (muy necesaria) para saber si la consulta ya está disponible, antes
de presentar los datos de esa consulta. La propiedad debe ser False para poder presentarlos.
Es típico crear un bucle parecido a este:

Do While GepaRs.StillExecuting = True


DoEvents
Loop

Transactions Devuelve un valor Booleano que indica si un rdoResultset permite


transacciones.

Type Devuelve un Long el tipo de rdoResultset. (0 = rdOpenForwardOnly, 1 = rdOpenKeyset,


2 = rdOpenDynamic, 3 = rdOpenStatic)

Updatable Devuelve un valor Booleano que indica si se pueden efectuar cambios en el


rdoresultset

Métodos del Objeto rdoResultset


El rdoResultset tiene algunos métodos comunes con el Recordset de DAO, sin embargo no se
puede esperar que funcionen siempre de la misma forma. En DAO era Visual Basic quien
abría la base de datos, y una base muy concreta, Access, dBase, etc., bases que controla
directamente Visual Basic a través de la dll correspondiente a la versión de la BD que vamos a
abrir. Esto no es exactamente igual en RDO. Aquí quien abre el fichero que contienen la base
de datos no es Visual Basic, sino el driver de ODBC. Y no solamente eso, dependiendo de la
base de datos, unas permiten hacer unas operaciones y otras no. Lo mismo podemos decir del
tipo de rdoResultset, del cursor y de si es lado cliente o lado servidor. Por lo tanto no se asuste
si pretende ejecutar un método y no funciona. Probablemente es que Visual Basic ha puesto
por defecto unas características a los objetos que no son las adecuadas. Y si no fuese posible,
en última instancia nos queda realizar directamente la operación que pretendíamos realizar
con el método, es decir, mediante las operaciones que nos permite el propio driver de ODBC.
Eso sí, en este caso estamos en sus manos. Lo veremos más adelante.

Método AddNew
Crea una nueva fila para un objeto rdoResultset actualizable.

Sintaxis MirdoResultset..AddNew

Funciona igual que el mismo método de DAO, se ejecuta el método AddNew, se introducen
los datos en los campos y se termina la operación con el método Update, que es cuando los
datos entran en la base de datos. Si se está usando cursores de tipo Client Batch los datos se
escribitrán en la BD cuando se ejecute el método BatchUpdate.
Hay que tener cuidado, pues el método AddNew no devuelve ningún error si se intenta añadir
una nueva fila a un rdoResultset no actualizable. Ese error va a salir cuando ejecutemos el
método Update. Para evitar este error hay que comprobar la propiedad Updatable del
rdoResultset.
Debe tener cuidado también con asegurarse que tras el método AddNew ejecuta el método
Update antes de cambiar de fila, ya que de no hacerlo se pierden los cambios realizados y VB
no avisa de ese error.

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 32


Si desea interrumpir la entrada de datos, una vez ejecutado el método AddNew puede anularse
usando el método CancelUpdate

MirdoResultset. CancelUpdate

La fila recién añadida no pasa a ser la fila actual. Sigue siendo fila actual la que era
anteriormente. Para que sea la nueva la fila actual basta con poner el siguiente código:

MirdoResultset.BookMark = MirdoResultset.LastModified

Pero eso sí, el rdoResultset debe aceptar marcadores. Para comprobarlo, se usa la propiedad
Bookmarkable.

Método BatchUpdate
Realiza una actualización optimista por lotes. Veamos que significa esto.
Este método solamente se puede aplicar a un rdoResultset del tipo Client Batch (Cuando se
crea el rdoResultset usando como tercer parámetro rdUseClientBatch) El tipo de rdoResultset
puede ser Keyset o Dynamic. En estas condiciones, cuando usamos el método Update para
guardar los datos, solamente se guardan en el rdoResultset local, pero no se meten en la base
de datos. Cuando se ejecuta este método, se envían a la base de datos todos los cambios
pendientes.

Sintaxis MirdoResultset.BatchUpdate (filaÚnica, forzar)

El parámetro filaÚnica es un Booleano que si es True, hace que la actualización sea solamente
de la fila actual. Si es False, se actualizan todas las filas pendientes.
forzar es tambiénun Booleano que si es True fuerza a escribir los valores, aunque puedan
causar colisiones.

Si usa el método CancelBatch, se descartan los cambios guardados en el objeto


rdoResultset local.

Método Close
Cierra un rdoResultset abierto. Es igual al método Close del Recordset de DAO

Sintaxis MirdoResultset.Close

Método Delete
Elimina la fila actual de un objeto rdoResultset actualizable.

Sintaxis MirdoResultset.Delete

Es posible deshacer la eliminación de una fila si emplea transacciones y el método


RollbackTrans, suponiendo que usa BeginTrans antes que el método Delete.

Se producirá un error al utilizar Delete si:

No hay ninguna fila actual.


La conexión o el rdoResultset es de sólo lectura.
Ninguna columna de la fila es actualizable.
La fila ya se ha eliminado.
Otro usuario ha bloqueado la que contiene la fila.
El usuario no tiene permiso para realizar la operación.

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 33


Método Edit
Inicia la operación de cambiar los valores de los datos de la fila actual o en un objeto
rdoResultset actualizable. Funciona de la misma forma que el método del mismo nombre del
Recordset de DAO. Al igual que en el método AddNew, es necesario terminar la operación con
el método Update.

Sintaxis MirdoResultset.Edit

Si cambia la fila actual antes de ejecutar el método Update, se perderán los cambios. Si desea
anular el cambio que está realizando, basta con ejecutar el método CancelUpdate.

Cuando la propiedad LockEdits del objeto rdoResultset es True (bloqueo pesimista), todas
las filas del conjunto de filas del objeto rdoResultset se bloquean en cuanto se ejecuta Edit, y
se mantienen bloqueadas hasta que se ejecuta Update.

Método GetRows
Recupera múltiples filas de un rdoResultset y las introduce en una matriz.

Sintaxis matriz = MirdoResultset.GetRows (filas)

Donde filas es el número de filas que se quieren recuperar. Es un Long


matriz es un Variant

El primer subíndice de la matriz identificará la columna y el segundo identifica el número de


fila, de esta forma:
matriz(intColumn)(intRow)
Método MoreResults

Este método se utiliza cuando se ha creado un rdoResultset de resultados múltiples, es decir,


se han empleado varias sentencias SELECT para crearlo. Cada sentencia formará dentro del
rdoResultset un juego de filas. Cuando se utiliza el método MoreResults se borran las filas del
conjunto de resultados actual y se colocan en su lugar las filas correspondientes al siguiente.
El método devuelve un Booleano que es True si ha encontrado un nuevo conjunto de
resultados, o False si no lo ha encontrado. No todas las bibliotecas de cursores son
compatibles con consultas de conjuntos de resultados múltiples. Por ejemplo, la biblioteca de
cursores del servidor no es compatible con este tipo de consultas si no desactiva el
procesamiento del cursor en un cursor de sólo lectura sólo hacia adelante con la propiedad
RowsetSize a 1.

Método Move
Cambia la posición de la fila actual en un objeto rdoResultset. Funciona igual que el mismo
método del Recordset de DAO

Sintaxis MirdoResultset.Move filas[, inicio]

Métodos MoveFirst, MoveLast, MoveNext y MovePrevious


Funciona de la misma forma que los métodos del mismo nombre en el Recordset de DAO.

Método Requery
Actualiza los datos de un objeto rdoResultset volviendo a ejecutar la consulta en la que está
basado el objeto.

Sintaxis MirdoResultset.Requery [opciones]

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 34


El valor admitidi para Opciones es rdAsyncEnable (32) que ejecuta la operación de forma
asíncrona

Método Update
Termina una operación de modificación de datos o de añadir una nueva fila. Ya se ha
comentado su funcionamiento con los métodos AddNew y Update.

No vamos a profundizar más en los objetos RDO. Su comportamiento es muy parecido a


DAO, exceptuando los nombres de los objetos, y las particularidades del ODBC en cuanto a
la situación de los cursores.
ODBC es una tecnología ya obsoleta (En el año 2002) y no debe emplearse para nuevos
proyectos. Lógicamente un curso de Visual Basic debe incluir RDO, pero siempre para
aplicarlo al mantenimiento de aplicaciones ya existentes. No se debe emplear para nuevos
proyectos, ya que si se quiere emplear ODBC es mucho más práctico y sencillo emplear
DAO en su versión de ODBCDirect. Tendrá código compatible con DAO, y más rapidez que
con RDO. Además RDO es una tecnología considerada obsoleta por Microsoft, con lo que
ello conlleva.
Microsoft dice, y este autor recomienda: USE ADO EN TODOS SUS NUEVOS
PROYECTOS

Pero si usa Access con la base de datos instalada en el mismo ordenador que el programa,
use directamente DAO. Si usa Access olvídese de nuevas tecnologías. Con Access DAO
significa: Rapidez, sencillez, eficacia, control sobre el programa, independencia de drivers.

LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 35

You might also like