48
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 LSB Visual Basic - Guía del estudiante. Capítulo 13 Página 1

Capitulo 13 Visual Basic

Embed Size (px)

DESCRIPTION

Manual de Visual Basic 6

Citation preview

Page 1: Capitulo 13 Visual Basic

Visual Basic - Guía del Estudiante Cap. 13

Acceso a Bases de Datos remotas mediante el motor JetODBCDirectAcceso a Bases de Datos remotas mediante objetos RDO

Acceso a Bases de Datos remotas mediante el motor JetODBCDirect

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 datosEl 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

Page 2: Capitulo 13 Visual Basic

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

Page 3: Capitulo 13 Visual Basic

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. LukiDescripció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

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

Page 4: Capitulo 13 Visual Basic

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

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/DeclaracionesOption Explicit 'Declaramos las variables tipo objetoDim MiSesion As WorkspaceDim MiConexion As ConnectionDim RsODBC As Recordset

Private Sub BCrearConexion_Click()'Se le dice al DBEngine que debe trabajar en el espacio de trabajo ODBCDirectDBEngine.DefaultType = dbUseODBCSet MiSesion = Workspaces(0)'Se crea el objeto conexiónSet MiConexion = MiSesion.OpenConnection("Conexion1", dbDriverNoPrompt, False, "ODBC;DSN=Luki")´Se crea el objeto RecordsetSet RsODBC = MiConexion.OpenRecordset("Personal", dbOpenDynamic, dbRunAsync, dbPessimistic)'Es necesario recorrer el recordset para conocer cuantos registros tiene (Es Dynaset)RsODBC.MoveLastRsODBC.MoveFirst

If RsODBC.AbsolutePosition <> -1 ThenLNumRegs = RsODBC.RecordCountLNumReg = RsODBC.AbsolutePosition + 1PresentaDatos

ElseMsgBox "La base de datos no tiene ningún registro"

End IfEnd Sub

Public Sub PresentaDatos()TB_ID = "": TB_Nombre = "" : TB_Apellido = ""

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

Page 5: Capitulo 13 Visual Basic

TB_ID = RsODBC!ID_AlumnoTB_Nombre = RsODBC!NombreTB_Apellido = RsODBC!ApellidosLNumReg = RsODBC.AbsolutePosition + 1End SubPrivate Sub BEliminar_Click()RsODBC.DeleteLNumRegs = RsODBC.RecordCountLNumReg = RsODBC.AbsolutePosition + 1If RsODBC.AbsolutePosition <> -1 ThenRsODBC.MoveFirstPresentaDatosEnd IfEnd Sub

Private Sub BGuardarDatos_Click()RsODBC.AddNewRsODBC!ID_Alumno = TB_IDRsODBC!Nombre = TB_NombreRsODBC!Apellidos = TB_ApellidoRsODBC.UpdateLNumRegs = RsODBC.RecordCountLNumReg = RsODBC.AbsolutePosition + 1End Sub

Private Sub BMas_Click()If RsODBC.AbsolutePosition <> -1 ThenRsODBC.MoveNext If RsODBC.AbsolutePosition <> -1 Then PresentaDatos Else RsODBC.MoveLast PresentaDatos End IfEnd IfEnd Sub

Private Sub BMenos_Click()If RsODBC.AbsolutePosition <> -1 ThenRsODBC.MovePrevious If RsODBC.AbsolutePosition <> -1 Then PresentaDatos Else RsODBC.MoveFirst PresentaDatos End IfEnd IfEnd Sub

Private Sub BMMas_Click()If RsODBC.AbsolutePosition <> -1 Then RsODBC.MoveLast PresentaDatosEnd IfEnd Sub

Private Sub BMMenos_Click()If RsODBC.AbsolutePosition <> -1 ThenRsODBC.MoveFirstPresentaDatos

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

Page 6: Capitulo 13 Visual Basic

End IfEnd Sub

Private Sub BNuevoReg_Click()LimpiaEnd SubPublic 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 = dbUseODBCVea 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

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

Page 7: Capitulo 13 Visual Basic

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 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

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

Page 8: Capitulo 13 Visual Basic

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 "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 JetDbOpenSnapshot 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 StillExecutingdbExecDirect  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

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

Page 9: Capitulo 13 Visual Basic

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 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 = TrueDoEventsLoop

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.

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

Page 10: Capitulo 13 Visual Basic

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 OpenConnectionObjeto QueryDef, para comprobar su método ExecuteRecordset, donde podrá comprobar si aún se están realizando los métodos Move, NextRecordset u OpenRecordset

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 = TrueAquí las instrucciones que quieraLoop

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 OpenConnectionQueryDef, para cancelar el método ExecuteRecordset 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

Page 11: Capitulo 13 Visual Basic

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 = dbUseODBCSet 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 ThenRsODBC.MoveLastRsODBC.MoveFirstLNumRegs = RsODBC.RecordCountLNumReg = RsODBC.AbsolutePosition + 1PresentaDatosElseMsgBox "El recordset no tienen ningún registro"End If

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

Page 12: Capitulo 13 Visual Basic

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 = dbUseODBCSet MiSesion = Workspaces(0)'En la siguiente línea le pasamos el nombre del enlace ODBC en el parámetro NombreSet 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 caracteresSet MiBaseDatos = MiSesion.OpenDatabase("BaseDatos1", dbDriverNoPrompt, False, "ODBC;DSN=Luki")'Ahora creamos el recordset, como en los otros casosSet RsODBC = MiBaseDatos.OpenRecordset("Personal", dbOpenDynaset, dbRunAsync, dbOptimistic)If RsODBC.AbsolutePosition <> -1 ThenRsODBC.MoveLastRsODBC.MoveFirstLNumRegs = RsODBC.RecordCountLNumReg = RsODBC.AbsolutePosition + 1PresentaDatosElseMsgBox "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

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

Page 13: Capitulo 13 Visual Basic

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 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

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

Page 14: Capitulo 13 Visual Basic

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 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 equivalentesObjeto de RDO Objeto de DAO/Jet equivalenterdoEngine DBEnginerdoError ErrorrdoEnvironment WorkspacerdoConnection DatabaserdoTable TableDefNo está implementado IndexrdoResultset RecordsetNo implementado Tipo TableTipo Keyset Tipo DynasetTipo static Tipo SnapshotTipo dynamic (ninguno)Tipo forward-only Tipo forward-onlyNo implementado (*) UserRdoColumn FieldrdoQuery QueryDefrdoParameter ParameterNo implementado (**) RelationNo implementado (*) GroupControl 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

Page 15: Capitulo 13 Visual Basic

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

Page 16: Capitulo 13 Visual Basic

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 StringMiVariable = "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

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

Page 17: Capitulo 13 Visual Basic

DatasourceName y el Control RemoteData le abrirá perfectamente la BD. Pero cuando 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 AlumnosSELECT * 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

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

Page 18: Capitulo 13 Visual Basic

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.

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 = valorMSRDC1.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 fila1 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 Efecto0 rdMoveLast Se mueve a la última fila1 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.

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

Page 19: Capitulo 13 Visual Basic

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 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

rdUseIfNeeded 0El controlador ODBC elegirá el tipo de cursores adecuado. Se 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.

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

Page 20: Capitulo 13 Visual Basic

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.

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 RemoteDataFilaunica (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

Page 21: Capitulo 13 Visual Basic

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

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

Page 22: Capitulo 13 Visual Basic

Propiedades del objeto rdoEngine

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 tablaRdUseIfNeeded (Predeterminado) elige el estilo de cursores más apropiado para el

ControladorRdUseODBC Utiliza la biblioteca de cursores ODBC. RdUseServer Utiliza cursores del servidorRdUseClientBatch Usa la biblioteca de cursores optimista por lotesRdUseNone 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 rdoEnginerdoCreateEnvironment 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

Page 23: Capitulo 13 Visual Basic

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 ODBCControlador 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.dllSilencio 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

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

Page 24: Capitulo 13 Visual Basic

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:

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 rdoConnectionSet 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 valoresrdDriverPrompt (0) Muestra el cuadro de diálogordDriverNoPrompt (1) No muestra nunca el Cuadro de diálogordDriverComplete (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 opcionesRequired que ya estén bien pasadas en la información facilitada.

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

Page 25: Capitulo 13 Visual Basic

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.

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

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

Page 26: Capitulo 13 Visual Basic

No se puede cerrar el rdoEnvironments(0) Si utiliza Close con el objeto ya cerrado, se producirá un error interceptable..

El objeto rdoConnectionUn 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 empleadoDATABASE Nombre de la base de datos que se va a emplearSERVER Nombre del servidor remotoWSIS Nombre de la estación de trabajo dentro de la redAPP 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

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

Page 27: Capitulo 13 Visual Basic

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

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.

SintaxisDim MiRs as rdoResultsetSet 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.StillConnectingEsta 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)

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

Page 28: Capitulo 13 Visual Basic

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 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 VBSet 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]]])

DondeMirdoResultset = variable tipo rdoResultset que debe estar declarada.MiConexión = Objeto Connection con el que se crea el rdoRsultsetNombre = 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 crearTipoBloq = Tipo de bloqueo de la base de datos. Por defecto, lo crea solo lectura.Opciones = Opciones que puede tener el rdoResultset

El argumento Tipo puede tener una de estos valores:

Constante Valor DescripciónrdOpenForwardOnly 0 (Predeterminado) Abre un rdoResultset tipo forward-only.rdOpenKeyset 1 Abre un rdoResultset tipo Keyset

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

Page 29: Capitulo 13 Visual Basic

rdOpenDynamic 2 Abre un rdoResultset tipo DinamicordOpenStatic 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

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

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

Page 30: Capitulo 13 Visual Basic

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

Page 31: Capitulo 13 Visual Basic

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

rdConcurReadOnly 1(Predeterminado) El cursor es de sólo lectura. No se admiten 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.

rdConcurBatch 5Concurrencia optimista con actualizaciones por lotes. Se obtienen 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

rdRowUnmodified 0(Predeterminado) La fila o la columna no se han modificado o se han actualizado correctamente.

rdRowModified 1La fila o la columna se han modificado y aún no se han actualizado en la base de datos.

rdRowNew 2La fila o la columna se han insertado con el método AddNew, pero aún no se han insertado en la base de datos.

rdRowDeleted 3La fila o la columna se han eliminado, pero aún no se han eliminado de la base de datos.

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

Page 32: Capitulo 13 Visual Basic

rdRowDBDeleted 4La fila o la columna se han eliminado localmente y también de la base de datos.

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 = TrueDoEventsLoop

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

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

Page 33: Capitulo 13 Visual Basic

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.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.

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

Page 34: Capitulo 13 Visual Basic

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.

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 Longmatriz 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.

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

Page 35: Capitulo 13 Visual Basic

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]

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