Make your own free website on Tripod.com

 

ACTIVE X DATA OBJECT (ADO)

 

 

ADO es lo último de Microsoft en acceso a bases de datos. No se porqué, pero desde su inicio, ADO está como metido en una aureola de dificultad a la que solamente pueden acceder informáticos especialmente elegidos. Quizás sea el uso de palabras de argot muy rebuscadas, que más que facilitar el estudio, atemorizan al principiante. La Guía del Estudiante pretende quitar esos velos que ocultan la sencillez de lo cotidiano y mostrar la facilidad de esta técnica. Con el estilo didáctico que caracteriza a este libro, pasaremos de las definiciones gloriosas e iremos a lo verdaderamente importante: saber programar con ADO 

 

ADO permite crear aplicaciones capaces de manipular bases de datos a través de un proveedor OLE DB (Object Linking and Embedding for DataBase). El objetivo de OLE DB es poner a disposición del programador una herramienta de nivel inferior que le de acceso universal a los datos con independencia del origen de datos, ya sea un servidor de correo electrónico, una hoja de cálculo u otro tipo de almacenamiento de datos. Debido a la complejidad de los elementos de OLE DB, no se puede acceder a ellos directamente desde Visual Basic; para ello utilizaremos los objetos ADO que permiten acceder a la práctica totalidad de las funciones de OLE DB.

Text Box: Aplicación que accede a los datos
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 



Las características generales de ADO son:

 

 

Las características específicas que proporciona ADO para entornos de Cliente/Servidor (C/S) son:

 

Hay que tener en cuenta que todas estas características están limitadas por el servidor de los datos. Es decir, si el servidor de datos no soporta procedimientos almacenados, no podremos utilizar con él las características de ADO que se refieren a dichos tipos de procedimientos.

 

Fig 72.1 Jerarquía de Objetos ADO.

 

 

 

 

 

 

 

 

 

 

 

 

 

 


* Todos los objetos marcados con un asterisco contienen la colección Properties con un subconjunto de objetos Property.

 

 

 

 


Como puede verse en la figura, existen tres objetos principales dentro de ADO: El objeto Connection, el objeto Command y el objeto recordset. Luego veremos algunas de las características principales de cada uno de estos objetos.

 

Antes de proseguir con estos objetos vamos a explicar donde y porqué se deben utilizar objetos ADO en vez de objetos DAO u objetos RDO

 

Hasta ahora habíamos utilizado bases de datos Access, y también otras bases de datos sencillas como dBase. Acceder a Access es extremadamente fácil. Y ello es debido a que Access es una base de datos sin grandes aspiraciones en cuanto a seguridad. Es una gran base de datos, y tiene sus dispositivos de seguridad en cuanto a permisos de acceso (Vea El dbEngine. Visión desde DAO y la propiedad SystemDB en el Capítulo 12) sin embargo estas posibilidades se usan en muy pocas ocasiones, y estos mecanismos de seguridad de Access tampoco son una maravilla. Por lo tanto Access se ha quedado como una gran base de datos para aplicaciones que no pasen de algunos centenares de miles de registros y con pocos puestos de operación. En esta base de datos, el método ideal de acceso es DAO, bien directamente o a través de ODBC Direct. Cuando se accede directamente, la BD se suele buscar bien mapeando el disco del servidor como una unidad más del puesto cliente, o bien accediendo a través de la dirección IP del servidor.

 

Cuando queremos empezar a tener una seguridad en los accesos, disponer de privilegios distintos para cada usuario, trabajar en una red de área local con muchos usuarios, hay que recurrir a bases de datos tipo Oracle o SQLServer.  Ya empezamos a tener problemas: Visual Basic no puede acceder directamente a abrir estas bases de datos. Podemos acceder a través de ODBC, pero como ya se dijo en el, capítulo correspondiente, ODBC se ha quedado obsoleto. Y Microsoft ha sacado para ello ADO. Y ADO permite abrir la base de datos usando para ello un dispositivo intermedio que es el proveedor OLE DB. Este no es más que una DLL.  Mejor dicho, un juego de DLLs que puede ver en la carpeta:

 

C:\Archivos de Programa\Archivos Comunes\System\Ado

 

Estas DLLs permiten conectar con las bases de datos más conocidas (Oracle, SQLServer, Access y las demás BD controladas por el motor Jet). ADO funciona de forma diferente a ODBC. Con ODBC se preparan conexiones permanentes en el ordenador, y cualquier programa puede acceder a la BD a través de esas conexiones. Con ADO no hay que preparar previamente ninguna conexión. Es el propio programa el que llama al proveedor de datos OLE DB y le pasa como parámetros los datos necesarios para que este realice la conexión y abra la BD. Si hubiese dos programas ejecutándose simultáneamente y accediendo a la misma base de datos a través de ADO, cada programa prepara una conexión a esa BD.  En ODBC podríamos ver las conexiones existentes en el PC a través del Panel de Control | Fuentes de Datos ODBC.  En ADO no existe esa posibilidad ya que, como se ha dicho, es el propio programa quien crea esa conexión al ajecutarse.

 

Para que VB pueda acceder a ADO es necesario introducir en el programa la referencia a  Microsoft ActiveX Data Objets 2.1 Library  (Proyecto|Referencias)

 

Una particularidad de ADO frente a lo ya visto con DAO o RDO es que ADO se salta la jerarquía a la hora de crear nuevos objetos. En DAO, el objeto DAO superior creaba al objeto DAO inferior (Recuerde aquello del juego de niños).  En ADO podemos crear cada objeto sin que exista el objeto inmediatamente superior.  Por ejemplo podemos crear un recordset sin que exista el objeto Connection. Claro que en este caso, a la hora de crear el objeto recordset deberemos indicarle, mediante los parámetros que debemos aportar en la sintaxis de creación del recordset, todos aquellos datos que le aportaríamos a la creación del objeto Connection. Como ve no tiene ventajas. Solamente que nos desentendemos un poco de abrir y cerrar el objeto Connection.

 

Veamos como se crea la conexión: Mediante el Objeto Connection

 

EL OBJETO CONNECTION

 

El objeto Connection representa una sesión con el origen de los datos. Dependiendo de la funcionalidad del proveedor de los datos podremos utilizar determinadas propiedades, métodos y colecciones de este objeto. La función de este objeto es recoger toda la información del proveedor de los datos que se va a utilizar para crear un objeto recordset.

 

Para crear un objeto Connection, previamente debemos declararlo como variable objeto Connection:

 

Dim MiConexion as ADODB.Connection

 

El sitio donde se debe declarar depende como siempre, del ámbito que deseamos que tenga ese objeto.

 

Para crear el objeto Connection deberemos utilizar la siguiente sintaxis:

 

Set MiConexion = New ADODB.Connection

 

Nota: En el caso de que ejecutemos la aplicación y nos salga un error diciendo que el tipo no está definido por el usuario, es que no hemos añadido la referencia de “Microsoft Actives Data Objects Library x.x”

 

La conexión ¿está creada?.  Sí, pero de momento es completamente inútil ya que no sabe ni siquiera que base de datos debe abrir, ni con que usuario, ni las condiciones en las que debe abrir esa base (Solo lectura, etc.)  Esta información se la pasamos mediante la propiedad ConnectionString (Cadena de conexión)

 

La propiedad ConnectionString

 

Es la propiedad más importante del objeto Connection. Se basa en encadenar una serie de argumentos en una cadena de caracteres. Los diferentes argumentos son (dependiendo del proveedor OLE DB y de la configuración de la red, se necesitarán todos o parte de ellos)

 

Provider           Especifica el nombre del proveedor que se usa en la conexión. (Oracle, SQLServer, Jet, etc)

Data Source     Especifica el nombre de la fuente de datos para la conexión. (Nombre de la base de datos a la que se va a acceder.

User Id             Especifica el nombre de usuario que abre la conexión. Debe ser un usuario ya declarado en la base de datos.

Password         Especifica la clave utilizada por el usuario para abrir la conexión. Debe coincidir con el que tiene ese usuario registrado en la Base de datos.

File Name        Especifica el nombre del fichero específico de proveedor, que contiene la información de configuración de la conexión. Este fichero es útil en instalaciones en red que requieran modificaciones de conexión frecuentes.

Remote Provider         Especifica el nombre de un proveedor de datos remoto cuando se utiliza una conexión cliente/servidor

Remote Server            Especifica el nombre del camino al servidor que se va a usar cuando se establece una conexión cliente/servidor

 

Como ejemplo para la conexión a una base de datos Oracle, con el usuario que esa BD tiene por defecto (scott) y el Password de este usuario (tiger) tendremos que especificar en el ConnectionString la siguiente cadena de caracteres.

 

‘Provider=MSDAORA.1;Password=tiger;User ID=scott;Data Source=MADRID;’

 

donde el valor de Source es la cadena de conexión de Oracle que previamente tiene que estar configurada con el SQL*Net o Net8 de Oracle.

 

Si lo que queremos es crear una conexión con una base de datos Access 2000

 

‘Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\GuiadelEstudiante\PruebaADO.mdb;’

 

Si la base de datos es de Access 97 entonces tendremos que especificar otro provider:

 

‘Provider=Microsoft.Jet.OLEDB.3.5;Data Source=C:\GuiadelEstudiante\db1.mdb;’

 


Para una base de datos SQLServer

 

"Provider=SQLOLEDB.1;Password=ayudas01; User ID=ayudas01; Initial Catalog=Ayudas_M; Data Source=ayudas_sql"    (en una línea única)

 

Como puede comprobar, resulta una tanto complicado construir la cadena de conexión y mientras que seamos novatos en ADO podemos tener problemas para crear esta cadena. ¿Pero es que no existe una manera más fácil de construir esta cadena? Efectivamente. Hay un pequeño truco mediante el cual no solo podemos crearla con un asistente, sino que además probaremos si la conexión es satisfactoria o no.

 

Truco para construir la cadena de conexión.

 

1)       Primero tenemos que incluir el componente “Microsoft ADO data control 6.0 (OLEDB)”. Podemos hacerlo pulsando Ctrl.-T o en el menú Proyecto à Componentes.

2)       Metemos en nuestro formulario el control y pulsamos F4 para ver sus propiedades.

3)       Hacemos Click en la propiedad ConnectionString y nos aparecerá el botón de puntos suspensivos. Hacemos Click en el  botón.

 

4)       Ahora nos aparece el asistente que nos mostrará 3 opciones. Utilizar un DSN de archivo, utilizar un controlador ODBC o utilizar una cadena de conexión. En todos los casos, a la derecha de la opción hay una opción que nos permite seleccionar o generar el origen de los datos. Usaremos la cadena de conexión (opción por defecto) y pulsaremos el botón generar.

 

 

 

 

5)       Al pulsar el botón generar, nos aparece otra ventana en la que tenemos cuatro pestañas aunque únicamente necesitaremos dos de ellas para crear una cadena de conexión correcta y probada. El resto de las pestañas forman parte de otro capítulo exclusivo del control data de ADO, aunque le invito a que curiosee por ellas. Seleccionaremos el proveedor de datos que queramos utilizar y pulsaremos el botón  siguiente para pasar a la siguiente pestaña.

 

 

6)       En la Pestaña conexión, tenemos que proporcionar los datos correspondientes al proveedor de la base de datos a la que queremos conectar. Por ejemplo para conectar con una base de datos de tipo MS Access (MS Jet 4.0 OLEDB Provider para la versión 2000 de Access, MS Jet 3.5 OLEDB Provider para la versión 97 de Access), tenemos que decirle el nombre y path de la BD. Para ello podemos utilizar el botón de los puntos suspensivos, que abrirá una ventana que permitirá seleccionar el archivo .mdb . Si utilizamos el proveedor de datos de Oracle, tendremos que indicarle como nombre de servidor la cadena de conexión utilizada en el SQL Net o en el Net8 de Oracle (la misma cadena que especifica cuando se conecta a través de SQL*Plus).

En esta pestaña existen dos opciones interesantes:

·         “Contraseña en Blanco”, si la marcamos no nos permitirá teclear la contraseña.

·         “Permitir guardar la contraseña”, dependiendo de si está o no seleccionada, incluirá o no en la cadena de conexión la clave del usuario. Para la primera prueba le recomiendo que la marque. No obstante, haga diferentes pruebas con ellas para ver los resultados.

Después de haber dado esta información, pulsaremos el botón Probar conexión. En el caso de que haya algún error, el asistente nos lo indicará con un mensaje.


Prueba de conexión (fallida) con Proveedor de datos de Oracle

                                                            Prueba satisfactoria

 

7)       Una vez que hemos probado satisfactoriamente la conexión, pulsaremos aceptar y volveremos a la pantalla inicial, la de las 3 opciones. La diferencia es que ahora tenemos la cadena de conexión rellenada por el asistente. Ahora podemos copiarla con ctrl.-C y llevarla a la parte del código donde queremos establecer la conexión. No se olvide de que es una cadena y que cuando se asigne a la propiedad ConnectionString debe ir entre comillas dobles.

8)       Una vez que hemos probado que funciona al abrir el objeto Connection, No debemos olvidarnos de eliminar el control data de ADO y de quitar el componente de nuestro proyecto, salvo que lo vayamos a utilizar para otra cosa.

 

Ya conocemos el truco para formar la cadena de conexión y se la hemos introducido en la propiedad ConnectionString  ¿Ya está creada la conexión? Sí, pero todavía no sirve para obtener datos de la base de datos. Pero ya hemos avanzado mucho. Ahora nuestro programa ya sabe al menos, como poder abrir esa base de datos, pues conoce su nombre, usuario que la abre y Password.  Solamente queda aplicar un método del objeto Connection: el método Open con una sintaxis que no es excesivamente difícil:

Miconexión.Open

 

La conexión se va a realizar a una base de datos que está en un servidor. Este servidor puede definirse, bien por su dirección IP o por su nombre. Lo normal es definirlo por su nombre (Server_SQL_Mae) y no por su dirección IP.  Obviamente el nombre del servidor corresponderá a una dirección IP (Vamos a considerar una red IP estática, pues si pretendemos entrar a explicar lo que es una red con direcciones IP asignadas dinámicamente se nos complica la explicación). Esa dirección IP debemos indicársela al PC en el fichero Hosts (o Lmhosts) que están en la carpeta Windows o en una de sus subcarpetas. En estos ficheros explica como hacerlo. No se extrañe si, una vez indicado en ese fichero, sigue sin encontrarlo. La primera conexión con el servidor la busca mediante llamadas broadcast en la red que no siempre son bien tratadas por los routers. En muchas ocasiones he tenido que buscar el servidor a mano (entorno de red) y, milagros de Windows, a partir de esa operación ya lo encuentra sin problemas.

 

 

Para seguir un poco el ejemplo que acompaña a este capítulo, vamos a ver el código utilizado para crear la conexión. En el ejemplo usamos una base de datos Access (No es la mejor para demostrar como funciona ADO, pero es la que los alumnos van a tener con mayor facilidad. Una base Oracle o SQL no se instala fácilmente en un ordenador personal)

 

Set MiConexion = New ADODB.Connection

'MiConexion.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\GuiaDelEstudiante\ADO\PruebaADO.mdb;Persist Security Info=False"

'MiConexion.Open

 

Ahora nuestro programa ya está en contacto con la base de datos. Lo que falta ya lo puede suponer: crear un recordset.

 

Aquí vamos a ver la primera diferencia con DAO. El recordset no lo crea el objeto Connection. Se crea él a sí mismo.  Para que pueda existir un objeto Recordset primero hay que declararlo:

 

Dim MiRecordset As ADODB.Recordset              (Hay que declararlo en el sitio adecuado dependiendo del ámbito que necesite)

 

En el procedimiento donde se vaya a crear el recordset, para crearlo utilizaremos la siguiente sintaxis:

 

Set MiRecordset = New ADODB.Recordset         (Ya está creado. Pero no está abierto, ahora hay que abrirlo)

 

MiRecordset.Open "Alumnos", MiConexion, adOpenDynamic, adLockOptimistic

 

Ya tenemos abierto el recordset. En este caso el recordset está formado por todos los registros con todos sus campos de la tabla Alumnos, que está en la base de datos definida en la conexión MiConexion, es del tipo Dynamic y el bloqueo de escritura es optimista.

 

Podríamos elegir ciertos registros, y solamente unos campos. Utilizaríamos una sentencia SQL

 

MiRecordset.Open "Select Alumno_Nombre, Alumno_Ape1, Alumno_Ape2 From Alumnos " _

& “Where Alumno_Nombre = ‘Luis’”, MiConexion, adOpenDynamic, adLockOptimistic

 

Si no hubiésemos creado previamente el objeto Connection, podríamos crear y abrir igualmente este objeto recordset, pero, en vez de pasarle el nombre de la conexión (MiConexion) le pasaríamos la cadena de conexión usada para crear ese objeto Connection.

 

 

 

 

Set MiRecordset = New ADODB.Recordset

MiRecordset.Open "Alumnos", "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\GuiaDelEstudiante\ADO\PruebaADO.mdb;Persist Security Info=False", adOpenDynamic, adLockOptimistic

(Es solamente una línea. Ha sido Word quien la ha troceado)

Ahora ya podemos presentar los campos del recordset, usando la sintaxis que ya conocemos de DAO

 

TbNombre = “” & MiRecordset!Alumno_Nombre

TbApe1 = “” & MiRecordset!Alumno_Ape1

TbApe2 = “” & MiRecordset!Alumno_Ape2

 

Hagamos una pequeña pausa. Observe que hay diferencias de trabajar con ADO o hacerlo con DAO.

 

Con DAO.

 

Declarar MiSesion, MiBase y MiRecordset

Dim MiSesion as Workspace

Dim MiBase As DataBase

Dim MiRecordset as Recordset

 

Crear el objeto Workspace, el objeto DataBase y el objeto Recordset

Set MiSesion = Workspaces(0)

Set MiBase = MiSesion.OpenDatabase (“C:\GuiadelEstudiante\Alumnos.Mdb”)

Set MiRecordset = MiBase.OpenRecordset (“Alumnos, dbOpenDynaset)

 

Con ADO  (Creando el objeto Connection)

 

Declarar MiConexion y MiRecordset

Dim MiConexion As ADODB.Connection

Dim MiRecordset As ADODB.Recordset

 

Crear la conexión y ponerle la cadena de conexión en su propiedad ConnectionString

Set MiConexion = New ADODB.Connection

MiConexion.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\GuiaDelEstudiante\ADO\PruebaADO.mdb;Persist Security Info=False"

 

Abrir el objeto Connection

MiConexion.Open

 

Crear el objeto recordset

Set MiRecordset = New ADODB.Recordset

 

Abrir el objeto Recordset                                   

MiRecordset.Open "Alumnos", MiConexion, adOpenDynamic, adLockOptimistic

 

Con ADO  (Sin crear el objeto Connection)

 

Declarar MiRecordset

Dim MiRecordset As ADODB.Recordset

 

Crear el Recordset

Set MiRecordset = New ADODB.Recordset

 

Abrir el Recordset

MiRecordset.Open "Alumnos", "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\GuiaDelEstudiante\ADO\PruebaADO.mdb;Persist Security Info=False", adOpenDynamic, adLockOptimistic

 

Observe siempre que tanto en las declaraciones del objeto Connection y del objeto Recordset, como en su creación,  debemos anteponer siempre la palabra ADODB

 

Tanto el objeto Recordset como el objeto Connection se deberán cerrar cuando ya no se utilicen, o al menos, al cerrar la aplicación. Esto es tanto más necesario cuanto mayor sea la seguridad de la base de datos que vamos a utilizar. En algunas bases de datos, dejar una sesión abierta significa dejar una aplicación zombie ejecutándose en el servidor, que habrá que cerrar desde su propio sistema operativo. Este problema no le va a ocurrir utilizando Access, pero como ya se dijo al principio, Access no es el mejor ejemplo de utilización de ADO. Para cerrar una sesión y un recordset utilizaremos el método Close

 

MiRecordset.Close

MiSesion.Close             (Recuerde que debe cerrar antes el recordset que la conexión)

 

 

¿Qué pasa con el equivalente del Workspace?

 

Cuando resumíamos en la página anterior el código a usar si usábamos DAO o ADO, parecía (aunque no fuese cierto) que podíamos asimilar estos objetos

 

DAO                                         ADO

 

Recordset                                 Recordset

DataBase                                  Connection

WorkSpace                               ¿

 

Efectivamente el Workspace no tiene algo que pudiésemos decir “equivalente”  en ADO.  Esto es debido a que ADO ya considera que el acceso desde los usuarios lo gestiona directamente la base de datos. Recuerde que el Workspace en DAO era una “sesión de trabajo” de la base de datos, donde podíamos asociar un Workspace a cada usuario. ADO ya le pasa a la BD el nombre del usuario y su Password para que la propia base de datos quien autorice a ese usuario.

 

Algunas cosas que le van a ocurrir cuando ya haya creado el recordset.

 

El empleo de bases de datos complejas en cuanto a seguridad nos va a obsequiar con limitaciones a los recordsets que vamos a abrir en ADO.  Y además esas sorpresas van a ser distintas si usa uno u otro tipo de base de datos. (nos centraremos solamente en Oracle y SQLServer.  Access,  con la modestia que le caracteriza, no va a dar ningún problema.)

 

Los recordsets abiertos mediante una consulta SQL (aquellos en los que seleccionamos parte de los registros mediante   Select … Where van a crearse solo de lectura. Independientemente de los parámetros que le pasemos a la hora de crearlos. La descripción del error va a ser algo así como que el cursor es solamente de lectura.  También observará con frecuencia, cuando intente ir a un registro anterior al actual, MiRecordset.MoveFirst, p.e.) que le enviará un error diciendo que el cursor es solamente de avance hacia a delante. Estos efectos los observará también cuando use la instrucción SQL Order By. No hay que arrojar la toalla solamente por esto. Cuando eso ocurra, lo que hay que hacer es volver a crear el recordset de forma que acepte escritura y movimiento hacia atrás.  Eso generalmente se logra abriendo el recordset con todos los registros de la tabla,  e incluyendo en él todos los campos.

 

En vez de :

MiRecordset.Open "Select Alumno_Nombre, Alumno_Ape1, Alumno_Ape2 From Alumnos " _

& “Where Alumno_Nombre = ‘Luis’”, MiConexion, adOpenDynamic, adLockOptimistic

 

usar esta otra alternativa:

 

MiRecordset.Open "Alumnos", MiConexion, adOpenDynamic, adLockOptimistic

 

Posiblemente necesitemos crear dos recordsets en un mismo procedimiento. Por ejemplo, es muy típico tener que buscar el último registro para ver el último número de un identificador de registro (Alumno_ID) y poner en este campo, al registro que vamos a crear, un número igual a ese más 1. En ese caso, abriríamos el recordset usando la sentencia Order By Alumno_ID.  Cuando queramos introducir un nuevo registro mediante:

 

MiRecordset.AddNew                 nos dirá que el cursor (el recordset, para entendernos) es solamente de lectura. La solución es, abrir el recordset con la sintaxis anterior, leer el número de Alunmo_ID, cerrar el recordset, crear otro recordset con el  mismo nombre, usando la sintaxis:

 

MiRecordset.Open "Alumnos", MiConexion, adOpenDynamic, adLockOptimistic

 

Ahora ya nos permitirá usar el método AddNew.  Basta con añadir las líneas de código adecuado para introducir los valores en cada campo:

 

Mirecordset.AddNew

MiRecordset!Alumno_ID = Valor numérico

MiRecordset!Alumno_Nombre = Valor string

Etc.

….

MiRecordset.Update

 

No renuncie nunca a intentar hacer esto. No siempre funciona. Pero esto es mucho más sencillo que introducir los datos “a capón”  utilizando la instrucción SQL Insert que ya veremos más adelante.  SQLServer es bastante más dócil que Oracle para usar el método AddNew.

 

A este respecto, hay que citar la propiedad CursorLocation que veremos más adelante. Si creamos un cursor lado cliente, seguramente nos permitirá utilizar más opciones (entre ellas AddNew) que si lo establecemos de lado servidor. Tenga en cuenta que si usa un cursor lado cliente, el recordset no se actualiza cuando otro usuario realiza modificaciones en la base.

 

Modificar datos mediante EDIT

 

En ADO no hace falta usar Edit para modificar los datos del registro actual. Edit no existe en ADO. Para modificar un dato basta con poner el mismo código que utilizábamos en DAO, pero sin comenzar por la línea Mirecordset.Edit. Colocándonos en el registro a modificar pondremos:

 

MiRecordset!Alumno_Nombre = “Pedro”

MiRecordset!Alumno_Ape1 = “Perez”

MiRecordset.Update

 

De cualquier forma, esto tampoco tiene porque funcionar en todas las bases de datos. En ese caso tendremos que recurrir, al igual que para un registro nuevo, a las instrucciones SQL, que en este caso será  Update.   Pero ya lo veremos más adelante.  Hasta ahora solamente he querido usar el código más simple para que pueda empezar con ADO, y sobre todo, para que vea que esta es una técnica completamente accesible, aunque, dadas las grandes prestaciones que tiene, un poco más adelante se va a complicar algo.

 

Ya ha visto que podemos trabajar perfectamente con recordsets, tal como lo hemos hecho con el DAO de toda la vida.  Pero ya lo comentábamos al principio, parece que hay que adornar lo obvio para que no lo parezca tanto. Y ahí viene el Objeto Command, que como habrá podido ver en la figura de la Jerarquía de los objetos ADO, es un objeto que aún no sabemos lo que hace.

 

El objeto Command lo que va a hacer es crear un recordset. O también, meter “a capón” un nuevo registro, o borrarlo, utilizando directamente instrucciones SQL.   Hay que darse cuenta que ADO trabaja con una gran diversidad de bases de datos, y no todas trabajan igual. Por eso, muchas veces fallan operaciones tan sencilla como añadir un nuevo registro con el método AddNew del recordset

 

MiRecordset.AddNew

 

Y hay que emplear una instrucción SQL: INSERT

 

En estos casos, en ADO utilizamos el método EXECUTE sobre el objeto Connection.  Creamos una variable, StrIntroducir, con el contenido de la instrucción SQL y ejecutábamos esa instrucción mediante Execute

 

StrIntroducir = "Insert Into INT_DOCUMENTOS " _

& "(CL_DOC,NOM_DOC,TITULO_DOC,AUTOR_DOC,CL_TEMA_DOC,CL_DPT_DOC,”  _

& “L_TIPO_DOC,FICH_DOC,FECHA_EMISION_DOC,ULTIMA_HORA_DOC,VISIBLE_DOC)"_ & "Values (" & NumeroDocumento & ",'" & TbTitulo & "','" & TbTitulo & "','" & TbTitulo.Tag  _

& "',19,2,1,'" & HRefPrensa & "/" & TbNombFichTIF & "','" & Date & "',0,1)"

 

ConexBDPrensa.Execute StrIntroducir

 

Esta línea (StrIntroducir) es el contenido de la propiedad CommandText de un objeto Command de ADO. Ni más ni menos que una instrucción que queremos realizar sobre la BD.  Un objeto Command tiene pocas cosas más.  Como objeto ADO que es tiene sus propiedades y métodos. Pero en esencia es lo que acaba de ver con la instrucción EXECUTE del objeto Connection. Lo que pasa, que ADO lo han hecho muy organizado, y por eso tiene la categoría de Objeto.  Es hacer lo mismo, utilizando las mismas expresiones, pero dándole más cuerpo.

 

Con la instrucción anterior, lo que hacíamos era añadir un registro.  Si lo que queremos hacer es crear un recordset, la instrucción SQL comenzaría por “Select * From ….” Y el método EXECUTE devolvería un Recordset

 

StrIntroducir = “Select * From Alumnos Where Apellido1 = ‘Suarez’”

 

Podemos crear un recordset (MiRecordset, previamente declarado como tal) con esta instrucción

 

MiRecordset = ConexBDPrensa.Execute StrIntroducir

 

O con estas otras

 

Set MiComando as New ADODB.Command

MiComando.ActiveConnection = ConexBDPrensa

MiComando.CommandText = “Select * From Alumnos Where Apellido1 = ‘Suarez’”

MiRecordset = MiComando.Execute

 

Verá el ejemplo completo al final del capítulo.

 

Ahora, tras la explicación informal de cómo se crea una conexión y un recordset en ADO, y que es un Command, vamos a entrar a conocer sus propiedades y métodos.  Al final, y con un buen ejemplo realizado de varias formas, entenderá perfectamente la forma de trabajar con ADO.

 

 

 


ADO.  El Objeto Connection

 

Un objeto Connection representa una conexión abierta con un origen de datos. Ya hemos visto como crear un objeto Connection, por lo que vamos a pasar directamente a ver sus objetos, colecciones, propiedades y métodos.

 

Como puede verse en la figura, el Objeto Connection tienen los objetos Command y Recordset, y la colección Errors.

 

El Objeto Recordset es el recordset de toda la vida: un conjunto de registros que contienen datos. El Objeto Recordset, aunque pertenece al objeto Connection, puede crearse sin que exista previamente un objeto Connection. Esta es una de las propiedades de los objetos ADO: no necesita cumplir estrictamente con la jerarquía.

 

El Objeto Command es una definición de un comando específico que se piensa ejecutar contra un origen de datos. Los objetos Command sirven para tener almacenadas operaciones de acceso a datos y usarlas en el momento adecuado, simplemente citándolas. Lo que obtenemos de un objeto Command es, o un recordset (verá que no merece la pena usar un objeto Command para crear un recordset, puesto que se pueden crear directamente) o una operación que afecte a los registros de la base de datos (añadir registros, borrarlos, si es que no se deja hacer eso mediante recordsets)

 

La Colección Errors es el conjunto de errores generados por el proveedor de datos ante el fallo de una operación de acceso. La colección Errors se refiere únicamente a los errores generados por el proveedor, no a los fallos interceptables producidos por el programa, que deben ser tratados de la forma habitual: mediante Err

 

Propiedades del Objeto Connection   (Lea esto de las propiedades sin complicarse demasiado la vida. Las realmente importantes verá que están advertidas debidamente)

 

Las propiedades del objeto Connection dependen de cada proveedor. No todos se comportan de igual forma, por lo que cada propiedad debe condicionarse a si el proveedor es capaz de ofrecerla.

 

Propiedad Attributes

 

Es un Long. Acepta dos valores o la suma de los dos:

 

            adXactCommitRetaining

            adXactAbortRetaining

 

Estos atributos condicionan el modo de operación de la conexión con los métodos CommitTrans y RollBackTrans.

Propiedad CommandTimeout

Indica, en segundos, el intervalo de espera para que se ejecute un comando (Objeto Command) antes de que finalice el intento y se genere un error. Es un Long. El valor predeterminado es 30.

Propiedad ConnectionTimeout

Indica, en segundos, el intervalo de espera para establecer una conexión antes de que finalice el intento y se genere un error. Es un Long y el valor predeterminado es 15.

Propiedad ConnectionString   (IMPORTANTE)

Es una cadena de caracteres que contiene la información que se utiliza para establecer una conexión a un origen de datos.  (Vea la explicación amplia más atrás)     

 

La cadena de conexión tiene varios argumentos, todos ellos separados por un punto y coma (;) de la forma  

argumento1 = valor; argumento2 = valor; argumento3 = valor   etc.

 

ADO procesa solamente cuatro argumentos: Provider, File Name, Remote Provider y Remote Server.  Los demás argumentos los pasa al proveedor para que el los procese (Usuario, Password, etc)

 

Si al emplear el método Open se utiliza el parámetro Connection String, este parámetro utilizado en el método Open sustituirá a cualquier otro existente anteriormente. Una vez abierta la conexión, esta propiedad no se puede cambiar puesto que es solamente de lectura.

Los argumentos File Name y Provider son excluyentes.

 

Propiedad CursorLocation    (IMPORTANTE)

Establece o devuelve la posición de un servicio de cursores. Es un Long, y acepta las siguientes constantes:

 

AdUseNone      No se usan servicios de cursor. (Esta constante es obsoleta y aparece                              únicamente por compatibilidad con versiones anteriores.)

AdUseClient     Usa cursores del lado del cliente.

AdUseServer    Predeterminado. Usa cursores del lado servidor.

 

Esta propiedad parece que no dice nada. Y es sumamente importante.

 

Los cursores son, por decirlo de alguna manera, los mecanismos de la base de datos donde se crean los recordsets. Se estará dando cuenta que las bases de datos que tienen cursores son ya bases de datos con mecanismos propios para la creación de recordsets. (SQL Server u Oracle, p.e.) Estas bases de datos trabajan como aplicaciones cliente – servidor. Tienen en el servidor, aparte de los datos, la mayoría de sus recursos. En el cliente tienen prácticamente los recursos de conectividad, y poco más. Esta conectividad permite enviar desde el cliente una petición a la base de datos alojada en el servidor. Esa petición será el resultado por ejemplo, de una sentencia SQL. Al recibirla el servidor, gestionará la obtención de los resultados y una vez que los haya conseguido viene su primera duda: ¿Dónde los almaceno? Puede almacenarlos en el servidor, y cada vez que necesitemos un nuevo registro, por ejemplo al ejecutar la sentencia MiRecordset.MoveNext, el cliente se lo indica al servidor y este le envía el nuevo registro.  También puede almacenar los datos obtenidos en el cliente, y de esta forma el cliente puede moverse con entera libertad a lo largo de los registros del recordset. Puede hasta contarlos y saber en que posición está. La diferencia entre uno y otro sistema es que en el primer caso el tráfico por la red es mínimo (solamente se envía la información estrictamente necesaria) y en el segundo caso, se envía mucha información de un golpe, la correspondiente a todos los registros del recordset, independientemente de si se va a usar en el servidor o no.

 

Considerando el tráfico generado, parece que es mejor crear los cursores en el lado servidor. Pero esto trae también sus dificultades. Nos priva de muchas propiedades del recordset. Una propiedad muy usada, AbsolutePosition, no la tienen los cursores de lado servidor, circunstancia que no nos debe sorprender, ya que al no estar todos los registros en el cliente, éste, aunque disponga de todos los datos guardados en todos los campos de un determinado registro, no puede saber que posición ocupa ese registro dentro de la totalidad de registros del recordset. Por lo tanto, usar cursores de lado cliente o lado servidor será siempre una decisión a tomar dependiendo de la velocidad de la red, de la memoria disponible en el cliente, de la complejidad del programa, etc.

 

Recuerde que por defecto, ADO crea cursores de lado servidor. Para que la conexión le cree todos los cursores de lado cliente basta ejecutar la instrucción:

 

                        MiConexion.CursorLocation = adUseClient

 

Si desea hacer transacciones, deberá crear cursores del lado servidor, ya que los de lado cliente no las admiten. Comprenderá según vaya programando y encontrándose con problemas, que esta propiedad es absolutamente importante.

 

Este valor debe establecerlo antes de crear la conexión. De esta forma, todos los cursores creados con esa conexión serán de lado cliente o lado servidor, según haya elegido. Pero muchas veces sería ideal que unos recordsets tuvieran el cursor de un tipo y otros de otro.  Los recordsets también tienen esta propiedad, por lo que puede elegir el lado deseado para cada recordset utilizando esta propiedad aplicada no a la conexión, sino al recordset.

 

El número de registros que el servidor envía al cliente, cuando el cursor es de lado servidor, se controla mediante la propiedad CacheSize del recordset. Lo verá más adelante.

 

Propiedad DefaultDatabase

Establece la base de datos predeterminada para un objeto Connection. Es un string con el nombre de la base de datos por defecto de esa conexión. Solamente es válida con aquellos proveedores que permiten varias bases de datos por conexión.

 

IsolationLevel

Esta propiedad afecta al comportamiento de un objeto Connection durante una transacción. Una vez establecida esta propiedad, solamente será efectiva cuando se invoque el método BeguinTrans.  Vea la ayuda para mayor información de los valores posibles.

 

Propiedad Mode,

Establece los permisos disponibles para modificar datos en un objeto Connection.

 

Los valores aceptados son:

 

AdModeUnknown        Predeterminada. Indica que los permisos no se han establecido aún o                               que no se pueden determinar.

AdModeRead               Indica que son permisos de sólo lectura.

AdModeWrite                Indica que son permisos de sólo escritura.

AdModeReadWrite      Indica que son permisos de lectura/escritura.

AdModeShareDenyRead         Impide que otros abran una conexión con permisos de lectura.

AdModeShareDenyWrite         Impide que otros abran una conexión con permisos de                                                      escritura.

 

AdModeShareExclusive           Impide que otros abran una conexión.

 

AdModeShareDenyNone         Impide que otros abran una conexión con cualquier tipo de                                                permiso.

 

Sólo puede establecer la propiedad Mode cuando el objeto Connection está cerrado. Cuando se usa en un objeto Connection del lado del cliente, la propiedad Mode sólo se puede establecer a adModeUnknown.

 

Propiedad Provider

Es un string que indica el nombre del proveedor de un objeto Connection. Si no se especifica ningún proveedor, la propiedad tendrá el valor predeterminado MSDASQL (Proveedor de Microsoft OLE DB para ODBC).

 

 

Propiedad State

Devuelve el estado del objeto Connection: abierto (adStateOpen = 1) o cerrado (adStateClosed = 0).

 

Propiedad Version

Devuelve el número de versión de ADO.  Es un String.

 

Métodos del Objeto Connection

 

Métodos BeginTrans, CommitTrans y RollbackTrans

Estos métodos de transacción administran el proceso de la transacción dentro de un objeto Connection de la forma siguiente:

·         BeginTrans: inicia una nueva transacción.

·         CommitTrans: guarda las modificaciones y termina la transacción actual. También puede iniciar una nueva transacción.

·         RollbackTrans: cancela las modificaciones efectuadas durante la transacción actual y termina la transacción. También puede iniciar una nueva transacción.

 

Después de invocar el método BeginTrans, el proveedor ya no aplicará inmediatamente las  modificaciones hasta que invoque CommitTrans o RollbackTrans para terminar la transacción. Los métodos BeginTrans, CommitTrans y RollbackTrans no están disponibles en los objetos Connection del lado del cliente.

 

 

Método Cancel

Cancela la ejecución de una llamada asíncrona pendiente a un método Execute u Open.

 

Sintaxis                        NombreConection.Cancel

 

El método Cancel se utiliza para terminar la ejecución de una llamada asíncrona a un método Execute o Open (es decir, el método fue invocado con la opción adAsyncConnect, adAsyncExecute o adAsyncFetch). Cancel devolverá un error de ejecución si no se utilizó adAsyncExecute en el método que quiere terminar.

 

Close, método

Cierra el objeto Connection.

 

Sintaxis                        NombredelObjetoConnection.Close

 

El cierre de un objeto Connection mientras hay objetos Recordset abiertos en la conexión cancela las modificaciones pendientes en todos los objetos Recordset. El cierre explícito de un objeto Connection (llamando a su método Close) mientras una transacción está en progreso genera un error. Si un objeto Connection cae fuera del alcance mientras la transacción está en progreso, ADO cancela automáticamente la transacción.

 

El cierre de un objeto Connection no lo elimina de la memoria; puede modificar los valores de sus propiedades y volver a abrirlo más tarde. Para eliminar completamente un objeto de la memoria, establezca la variable de objeto a Nothing.

 

                        Set NombredelObjetoConnection = Nothing

 

Método Execute   (Vea también Método Execute para el objeto Command)

Ejecuta una consulta, instrucción SQL, procedimiento almacenado especificados o texto específico del proveedor.

 

Sintaxis            (Para una cadena de comando que no devuelva filas):

 

conexión.Execute CommandText, RecordsAffected, Options

 

(Para una cadena de comando que devuelva filas):

 

Set MiRecordset = connection.Execute (CommandText, RecordsAffected, Options)

 

(MiRecordset debe ser una variable declarada tipo ADODB.Recordset)

 

CommandText Es un String que contiene la instrucción SQL, el nombre de la tabla, el procedimiento almacenado o el texto específico del proveedor que se va a ejecutar.

RecordsAffected Opcional. Una variable Long en la que el proveedor devuelve el número de registros afectados por la operación.

Options Opcional. Una constante o valor Long que indica cómo debe evaluar el proveedor el argumento CommandText. Puede ser uno de los siguientes valores.

 

Constante

Descripción

adCmdText

Indica que el proveedor tiene que evaluar CommandText como definición textual de un comando, como una instrucción SQL.

adCmdTable

Indica que ADO tiene que generar una consulta SQL para devolver todas las filas de la tabla mencionada en CommandText.

adCmdTableDirect

Indica que el proveedor tiene que devolver todas las filas de la tabla mencionada en CommandText.

adCmdTable

Indica que ADO tiene que generar una consulta SQL para devolver todas las filas de la tabla mencionada en CommandText.

adCmdStoredProc

Indica que el proveedor tiene que evaluar CommandText como procedimiento almacenado.

adCmdUnknown

Indica que el tipo de comando en CommandText es desconocido.

adAsyncExecute

Indica que el comando se tiene que ejecutar de forma asíncrona.

adAsyncFetch

Indica que el resto de las filas siguientes a la cantidad inicial especificada en la propiedad CacheSize tiene que ser recuperada de forma asíncrona.

 

Cuando esta operación termina se genera el evento ExecuteComplete.

 

Método Open               (IMPORTANTE)

Abre una conexión a un origen de datos.

 

Sintaxis                        MiConnection.Open ConnectionSTring, UserID, Password, Options

 

                        MiConnection.Open

 

Los parámetros ConnectionSTring, UserID, Password, Options puede introducirlos previamente a abrir la conexión, y utilizar la segunda sintaxis cuando desee abrirla realmente. Estos parámetros se le pasan en la cadena de conexión:

 

ConexBDPrensa.ConnectionString = "Provider=MSDAORA.1;User ID=INTRANET;” & _

“Password=INTRANET;Data Source=intranet;Persist Security Info=False"

 

Options Opcional. Puede ser una de las constantes siguientes:

 

            AdConnectUnspecified   Abre la conexión de forma sincronía

            AdAsyncConnect           Abre la conexión de forma asíncrona

 

Cuando se usa un objeto Connection del lado del cliente, el método Open no establece realmente una conexión con el servidor hasta que se abre un Recordset del objeto Connection.

Colecciones del Objeto Connection

Colección Errors

Contiene todos los objetos Error creados en respuesta a un único fallo relacionado con el proveedor. Cada objeto Error representa un error específico del proveedor, no un error ADO. Los errores ADO se exponen al mecanismo de control de excepciones en tiempo de ejecución. Por ejemplo, en Microsoft Visual Basic, cuando ocurre un error específico de ADO dispara un evento On Error y aparece en el objeto Err.

 

Cuando otra operación ADO genera un error, se borra la colección Errors y el nuevo conjunto de objetos Error se coloca en la colección Errors. Las operaciones ADO que no generan un error no tienen ningún efecto sobre la colección Errors. Para borrar manualmente la colección Errors utilice el método Clear.

 

Cada objeto Error de la colección, nos dará información sobre un error producido en la conexión. Sus propiedades son las siguientes:

Debido a que este objeto será de gran utilidad a continuación se incluye un ejemplo de su uso.

Text Box: Private Sub CBConexion_Click()
Dim MiConex1 As ADODB.Connection
Dim MiError As ADODB.Error
On Error GoTo RutErr
Set MiConex1 = New ADODB.Connection
MiConex1.ConnectionString = "Provider=MSDAORA.1;Password=tiger;User ID=EScot;Data Source=MADRID;Persist Security Info=True"
MiConex1.Open
Exit Sub
RutErr:
For Each MiError In MiConex1.Errors
   MsgBox ("Error VB:" & MiError.Number & vbCrLf _
   & "Error Oracle:" & MiError.NativeError & vbCrLf _
   & "Error SQL:" & MiError.SQLState & vbCrLf _
   & "Generado Por:" & MiError.Source & vbCrLf _
   & "Descripción:" & MiError.Description)
Next
End Sub
Ejemplo del tratamiento de errores:

El resultado de la ejecución es el siguiente:

 

 

Como puede observarse, algunas de las propiedades no devuelven los valores esperados: NativeError vale 0 cuando debería valer –1017, que es el error asociado de Oracle. Aún así podemos capturar el código del error desde la cadena de caracteres description. Con este comentario se pretende sugerir que se realicen pruebas con el proveedor de datos que vayamos a utilizar para conocer su comportamiento respecto a este objeto error y dónde nos devuelve los códigos.

 

Observese en el código que la declaración de MiError se hace con ADODB.Error

 

Colección Properties

 

Es el conjunto de objetos Property

Objeto Property

Un objeto Property representa una característica dinámica de un objeto ADO que está definida por el proveedor.


 


Los objetos ADO tienen dos tipos de propiedades: intrínsecas y dinámicas.

Las propiedades intrínsecas son aquellas propiedades implementadas en ADO e inmediatamente disponibles para cualquier nuevo objeto, utilizando la sintaxis Objeto.Propiedad. No aparecen como objetos Property en la colección Properties de un objeto, de forma que aunque puede modificar sus valores, no puede modificar sus características.

 

Las propiedades dinámicas están definidas por el proveedor de los datos y aparecen en la colección Properties del objeto ADO apropiado. Por ejemplo, una propiedad específica del proveedor puede indicar si un objeto Recordset acepta transacciones o actualizaciones. Estas propiedades adicionales aparecerán como objetos Property en la colección Propiedades de dicho objeto Recordset. A las propiedades dinámicas se les puede hacer referencia sólo a través de la colección, utilizando la sintaxis Objeto.Properties(0) u Objeto.Properties("Name").

 

Un objeto Property dinámico tiene cuatro propiedades incorporadas propias:

·         La propiedad Name es una cadena que identifica la propiedad.

·         La propiedad Type es un entero que especifica el tipo de datos de la propiedad.

·         La propiedad Value es un variant que contiene el valor de la propiedad.

·         La propiedad Attributes es un valor Long que indica características de la propiedad específicas del proveedor.

 

 

 

El Objeto Recordset de ADO

 

El objeto Recordset representa un conjunto de registros. El recordset en ADO puede crearse abriéndolo, tomando todos los registros de una tabla o seleccionándolos con una consulta SQL, o ejecutando un comando que contienen el nombre de esa tabla o la consulta. En un momento determinado, el objeto Recordset sólo hace referencia a un único registro dentro del conjunto de registros, llamado registro actual.

 

Propiedades del Objeto Recordset

 

El recordset de ADO tiene propiedades iguales al recordset de DAO, pero tienen otras que no tienen el de DAO. Se van a estudiar todas, profundizando más en las que son particulares del recordset ADO.

Propiedad AbsolutePosition (ADO)

Especifica la posición ordinal del registro actual de un objeto Recordset. Esta propiedad devuelve un Long con el número de orden del registro. Es posible que el recordset no acepte esta propiedad, dependiendo del proveedor de datos, y  del tipo de cursor (lado cliente o lado servidor.  El cursor tipo lado servidor no permite esta propiedad)  Esta propiedad devolverá 1 cuando el registro actual sea el primer registro del recordset.

 

Propiedades BOF y EOF

Indican si la posición del puntero del Recordset está apuntando a un registro anterior al primero (BOF = True) o posterior al último (EOF = True). Esta propiedad siempre la podremos mirar, independientemente si el cursor es lado cliente o lado servidor.

 

Propiedad ActiveConnection (ADO)

Indica a qué objeto Connection pertenece actualmente el objeto Recordset especificado. Devuelve un string con el nombre del objeto Connection.

 

Propiedad Bookmark

Devuelve un marcador que identifica unívocamente al registro actual de un objeto Recordset o establece el registro actual de un objeto Recordset al registro identificado por un marcador válido. El valor del Bookmark hay que introducirlo en una variable tipo Variant.

 

La propiedad Bookmark solo podrá establecerse cuando el proveedor lo permita. Puede utilizarse el método Supports para averiguarlo.  Cuando el recordset es de lado cliente, siempre está disponible el Bookmark.

 

Propiedad CacheSize

Indica el número de registros del objeto Recordset que están en la memoria caché local. Es un Long de lectura y escritura. El valor predeterminado es 1.

 

Esta propiedad nos permite conocer cuantos registros están en la memoria local. Si ponemos esta propiedad por ejemplo a 10, al abrir la primera vez el objeto Recordset, el proveedor recupera los 10 primeros registros en la memoria local. A medida que se desplaza por el objeto Recordset, el proveedor devuelve los datos desde el búfer de memoria local. Tan pronto como pasa del último registro de la memoria caché, el proveedor recupera los 10 registros siguientes desde el origen de datos y los carga en la memoria caché.

Los registros recuperados desde la memoria caché no reflejan los cambios concurrentes que hagan otros usuarios en el origen de datos. Para forzar una actualización de todos los datos en la memoria caché, debe usarse el método Resync.

 

Propiedad MaxRecords

Indica el número máximo de registros que se devuelven a un Recordset desde una consulta. Es un Long y el valor predeterminado es 0, que significa sin límite (Obtienen todos los registros). Esta propiedad es de lectura y escritura cuando el recordset está cerrado, y solamente de lectura cuando está abierto.

 

Esta propiedad debe usarse solamente cuando se prevé que se pueden obtener un número muy grande de registros. Es prudente tomar medidas frente a aquellas operaciones en las que el ordenador pueda meterse en un proceso excesivamente largo o que ocupe más recursos de los disponibles. Estas cosas son las que suelen “colgar” al ordenador y en las que es muy frecuente echarle luego la culpa a Windows  Si estamos frente a una base de datos con todos los datos de los afiliados a la Seguridad Social, no es del todo prudente crear un recordset mediante esta sentencia:

 

            SELECT * From Afiliados Where Apellido1 = ‘Fernandez’

 

Incluso las hay peores:

 

            SELECT * From Afiliados

 

A nadie se le ocurriría, pero puede surgir involuntariamente cuando ese acceso se realiza desde un puesto de operación público (Acceso desde Internet por ejemplo).  Con la propiedad MaxRecords puede limitar el número de registros obtenidos. Posiblemente no llegue a obtener el dato deseado, y se vea en la obligación de realizar la misma consulta sucesivas veces hasta encontrarlo.

 

Propiedad CursorLocation

Establece o devuelve la posición de un servicio de cursores.  Es idéntica a la propiedad del mismo nombre vista más atrás con todo detalle para el objeto Connection.

 

Propiedad CursorType

Indica el tipo de cursor que se usa en un objeto Recordset. Es de lectura y escritura si el recordset está cerrado, y solo de lectura si está abierto. Puede tomar uno de los siguientes valores:

 

AdOpenForwardOnly   Predeterminado. Idéntico a un cursor estático, excepto sólo permite desplazarse hacia delante en los registros. Esto mejora el rendimiento en situaciones en las que sólo se quiere pasar una vez por cada registro.

 

En muchas ocasiones es necesario moverse por el recordset hacia delante y hacia atrás. Este tipo de cursor solamente permite moverse hacia delante. Tenga presente que este es el tipo predeterminado.

 

AdOpenKeyset Cursor de conjunto de claves. Igual que un cursor dinámico, excepto que no se pueden ver los registros que agregan otros usuarios, aunque los registros que otros usuarios eliminan son inaccesibles desde su conjunto de registros. Los cambios que otros usuarios hacen en los datos permanecen visibles.

 

AdOpenDynamic    Cursor dinámico. Las incorporaciones, cambios y eliminaciones que hacen otros usuarios permanecen visibles, y se admiten todo tipo de movimientos entre registros, a excepción de los marcadores si el proveedor no los admite.  Es el equivalente en DAO al tipo Dynaset

 

AdOpenStatic    Cursor estático. Una copia estática de un conjunto de registros que se puede usar para buscar datos o generar informes. Las incorporaciones, cambios o eliminaciones que hacen otros usuarios no son visibles.  Es el equivalente en DAO al tipo Snapshot

 

NOTA.  Si un proveedor no admite el tipo de cursor solicitado, el proveedor puede que devuelva otro tipo de cursor. La propiedad CursorType cambiará para coincidir con el tipo de cursor en uso cuando el objeto Recordset se abra. Para comprobar la funcionalidad específica del cursor devuelto, use el método Supports. Cuando cierre el Recordset, la propiedad CursorType volverá a su configuración original.

 

 

Propiedad LockType

Indica el tipo de bloqueo que se pone en los registros durante el proceso de edición. Establece también si el recordset se actualiza registro a registro o por lotes. Este último sistema permite realizar varios cambios en el recordset y mantenerlos en la caché durante cierto tiempo, y proceder a la actualización de todos los cambios pendientes en una sola operación. Esto es muy importante cuando se está trabajando con una base de datos situada en un servidor con un acceso lento (conexión vía Internet, por ejemplo)

 

Los valores de la propiedad LockType pueden ser:

 

AdLockReadOnly         Predeterminado. Sólo lectura—no puede modificar los datos

AdLockPessimistic       Bloqueo pesimista, registro a registro: el proveedor hace lo necesario                                para asegurar la modificación correcta de los registros, generalmente                            bloqueando registros en el origen de datos durante todo el proceso de                                  modificación. Este valor solamente es válido si el cursor (Propiedad                                   CursorLocation) esta establecido a lado servidor.

AdLockOptimistic         Bloqueo optimista, registro a registro: el proveedor usa bloqueo                                         optimista, bloqueando registros sólo cuando llama al método Update.

AdLockBatchOptimistic            Actualizaciones optimistas por lotes: requerido para el modo de                                        actualización por lotes como contraposición al modo de                                                    actualización inmediata.

 

Propiedad EditMode

Indica el estado de modificación del registro actual. Es solamente de lectura. Devuelve uno de las siguientes constantes:

 

AdEditNone                  Indica que no hay ninguna operación de modificación en ejecución.

AdEditInProgress         Indica que los datos del registro actual se han modificado pero que no                               se han guardado.

AdEditAdd                    Indica que se ha invocado el método AddNew y que el registro situado                               actualmente en el búfer de copia es un nuevo registro que no se ha                              guardado en la base de datos.

AdEditDelete                Indica que el registro actual se ha eliminado.

 

 

 

Propiedad Filter

 

Esta propiedad solamente la tienen los recordset ADO. Y es que ADO presupone que está obteniendo datos de una base de datos alojada en un servidor y que la comunicación entre servidor y cliente puede ser especialmente lenta. Mediante Filter puede descartar registros que no cumplan una determinada condición. En realidad lo que hacemos mediante Filter es crear un nuevo Recordset a partir de otro Recordset.

 

La propiedad Filter se utiliza también para actuar sobre determinados registros en varios métodos del recordset (Resync, Save, …) pero no se va a explicar en este manual la explicación de la utilización de esta propiedad en esos métodos, ya que el nivel del programador que utiliza esos recursos debe ser elevado. Le reservamos por tanto la posibilidad de conocerlo directamente desde la ayuda de Visual Basic, que en este caso es bastante buena.

 

De momento lo que vamos a hacer con Filter es crear un nuevo recordset ¿Por qué no creamos directamente el nuevo recordset utilizando una sentencia SQL que lleve implícito ese filtro?

Personalmente no me gusta utilizar la propiedad Filter, y prefiero crear un nuevo recordset. Creo que solamente lo he usado para rellenar un MSHFlexGrid con parte de los datos del recordset que uso en una parte de la aplicación.  Veamos un ejemplo:

 

(MiConexion es una conexión ya creada)

Dim RsInicial As ADODB.Recordset

Dim RsFiltrado As ADODB.Recordset

Set RsInicial = New ADODB.Recordset

Set RsFiltrado = New ADODB.Recordset

RsInicial.Open "Autores", MiConexion, adOpenDynamic, adLockOptimistic

 

‘Este es el recordset que uso para muchas cosas dentro de la aplicación. Ahora quiero presentar en un MSHFlexGrid solamente los datos de los autores de nacionalidad española. Filtro el recordset anterior utilizando un criterio de igualdad de un campo: Nacionalidad

 

RsFiltrado = RsInicial.Filter (“Nacionalidad = ‘Española’”)

 

‘Ahora ya podemos aplicar este recordset al MSHFlexGrid:

 

Set MSHFlexG1.Recordset = RsFiltrado

 

‘Y cuando queremos presentar todos los autores, basta con poner la línea:

 

Set MSHFlexG1.Recordset = RsInicial

 

Este es el único ejemplo que puedo sacar de todas mis aplicaciones. Seguro que el alumno va a ver más aplicaciones de esta propiedad.


La propiedad Filter puede mostrar también aquellos registros que han sido manipulados recientemente, mediante las constantes siguientes:

 

AdFilterNone                           Quita el filtro actual y vuelve a poner todos los registros a la

vista.

AdFilterPendingRecords          Permite ver sólo los registros que han cambiado, pero que no                                            han sido enviados aún al servidor. Aplicable sólo para el modo                                                 de actualización por lotes.

AdFilterAffectedRecords          Permite ver sólo los registros afectados por la última llamada a                                         Delete, Resync, UpdateBatch o CancelBatch

AdFilterFetchedRecords          Permite ver los registros de la caché actual, es decir, los                                      resultados de la última llamada para recuperar registros de la                                                base de datos

AdFilterConflictingRecords      Permite ver los registros que fallaron en el último intento de                                               actualización por lotes.

 

 

Propiedad Index

Indica el nombre del índice que se utiliza actualmente en el Recordset. Es un String con el nombre del índice.

 

El índice se utiliza para moverse a lo largo del recordset mediante el método Move. El índice ya debe estar creado en la tabla de la base de datos.

 

Al utilizar un índice, el orden de los registros se cambia al orden establecido en ese índice. Por lo tanto, los valores obtenidos anteriormente por la propiedad AbsolutePosition cambiarán completamente.

No todos los proveedores de datos aceptan la propiedad Index. Puede comprobarlo mediante el método Supports.

 

Propiedad MarshalOptions

Esta propiedad se usa cuando estamos trabajando con cursores lado cliente. En este caso, como vimos más atrás, los registros del recordset están en el equipo cliente. Todas las operaciones realizadas sobre el recordset se realizan en el cliente, por lo tanto llegará el momento en que habrá que actualizar en el servidor los datos que hayamos modificado en el recordset que está en el equipo cliente. Mediante esta propiedad podemos hacer que se envíen al servidor todos los registros (filas) o solamente los que han cambiado. Acepta estas dos constantes:

 

AdMarshalAll                           Predeterminada. Indica que todos los registros se devuelven al                                          servidor.

AdMarshalModifiedOnly          Indica que sólo los registros modificados se devuelven al                                       servidor.

 

Esta propiedad puede mejorar el rendimiento de la aplicación para aquellos casos en los que se use un canal de comunicación lento.

 

Propiedad PageSize

Indica cuántos registros constituyen una página del objeto Recordset. Es de lectura y escritura. Devuelve un Long y su valor predeterminado es 10.

 

Esta propiedad permite determinar cuántos registros componen una página lógica de datos. Al establecer un tamaño de página, puede utilizar la propiedad AbsolutePage y se moverá al primer registro de una página específica. Esto es útil en las situaciones de servidor Web cuando se desea permitir que el usuario pase páginas de datos y vea cierto número de registros al mismo tiempo. Esta propiedad se puede establecer en cualquier momento y su valor se utilizará para calcular la ubicación del primer registro de una página específica.

 

Propiedad PageCount

Indica cuántas páginas de datos contiene el objeto Recordset. Es solamente de lectura. Devuelve un Long. Si el objeto Recordset no admite esta propiedad, el valor será -1 para indicar que no se puede determinar el valor de PageCount.

 

Propiedad AbsolutePage

Especifica en qué página reside el registro actual. Es de lectura y escritura. Devuelve un Long o una de las siguientes constantes:

 

AdPosUnknown           El objeto Recordset está vacío, la posición actual se desconoce o el                                proveedor no admite la propiedad AbsolutePage.

 

AdPosBOF                   El puntero del registro actual está al comienzo del archivo (es decir, la                               propiedad BOF tiene el valor True).

 

AdPosEOF                    El puntero del registro actual está al final del archivo (es decir, la                           propiedad EOF tiene el valor True).

 

Propiedad RecordCount

Indica el número actual de registros de un objeto Recordset.  Devuelve un Long

Es posible que esta propiedad no la permita el proveedor de datos, o que no pueda llegar a averiguarse, ya que dependiendo del tipo de cursor utilizado puede que no suministre ese dato.

 

Propiedad Source

Devuelve la tabla, consulta o sentencia SQL utilizado en el método Open para crear el recordset. Es un String.

 

Propiedad State

Indica el estado (abierto, cerrado, proceso de ejecución) en el que se encuentra el recordset. Devuelve uno de los siguientes valores:

 

Constante

Descripción

adStateClosed

Valor predeterminado. Indica que el objeto está cerrado.

adStateOpen

Indica que el objeto está abierto.

adStateConnecting

Indica que el objeto Recordset se está conectando.

adStateExecuting

Indica que el objeto Recordset está ejecutando un comando.

adStateFetching

Indica que se está obteniendo el conjunto de filas del objeto Recordset.

Puede tener una combinación de valores. Por ejemplo, si se está ejecutando una instrucción, esta propiedad tendrá un valor combinado de adStateOpen y adStateExecuting.

 

Propiedad Status

Esta propiedad se refiere al registro actual. Indica el estado de este registro respecto a las operaciones de actualización por lotes u otras operaciones masivas. No es una propiedad que se use todos los días.  Vea la ayuda para mas detalles.

 

Propiedades dinámicas del objeto recordset

 

Las propiedades anteriores se refieren a propiedades del recordset que se refieren a unas características propias del recordset una vez creado. Son estas:

 

Unique Table, Unique Schema y Unique Catalog

 

Unique Table especifica la tabla sobre la que se permite realizar modificaciones de datos (Insertar o actualizar), en el caso de que el recordset se haya creado mediante una operación JOIN

 

Unique Schema indica el nombre del propietario de la tabla

Unique Catalog indica el nombre de la base de datos a la que pertenece la tabla. Estas dos últimas propiedades deben tener un valor para poder poner valor a la propiedad Unique Table. Estas propiedades son tipo String

 

Estas propiedades dinámicas se anexan a la colección Properties del objeto Recordset al asignar el valor adUseClient a la propiedad Cursor Location.

 

 

Métodos del objeto Recordset de ADO

METODO Supports

Este método es muy útil para ver si un recordset acepta una determinada funcionalidad. Devuelve un Booleano y es solamente de lectura. De esta forma puede consultar si un recordset admite el método MoveFirst, la propiedad AbsolutePosition, Bookmark, etc., antes de invocar ese método o leer esa propiedad, y evitar de esta forma un error en la ejecución. Esto es muy útil habida cuenta que no todos los proveedores funcionan de la misma forma. Es por lo tanto muy prudente consultar si el Recordset soporta una funcionalidad antes de pedírsela.

 

Estas funcionalidades se le pasan como parámetro mediante una de las siguientes constantes:

 

AdAddNew                   Puede usar el método AddNew para agregar nuevos registros.

AdApproxPosition        Puede leer y establecer las propiedades AbsolutePosition y                                              AbsolutePage.

AdBookmark                Puede usar la propiedad Bookmark para tener acceso a registros                          específicos

AdDelete                      Puede usar el método Delete para eliminar registros.

AdHoldRecords            Puede recuperar más registros o cambiar la posición de recuperación                                siguiente sin efectuar todos los cambios pendientes.

AdMovePrevious          Puede usar los métodos MoveFirst y MovePrevious, y los métodos                                    Move o GetRows para desplazar hacia atrás la posición del registro                                  actual sin que se requiera marcadores.

AdResync                     Puede usar el método Resync para actualizar el cursor con los datos                                visibles en la base de datos subyacente.

AdUpdate                     Puede usar el método Update para modificar datos existentes.

AdUpdateBatch            Puede usar actualización por lotes (métodos UpdateBatch y                                             CancelBatch) para transmitir grupos de cambios al proveedor.

AdIndex                       Puede utilizar la propiedad Index para dar nombre a un índice.

AdSeek                        Puede utilizar el método Seek para encontrar una fila en un Recordset.

 

En este ejemplo vemos la sintaxis de Supports:

 

If RsSeg.Supports(adApproxPosition) = True Then

MsgBox "SI"

Else

MsgBox "NO"

End If

 

Nota Aunque el método Supports puede devolver True para una funcionalidad determinada, eso no garantiza que el proveedor pueda hacer que la característica esté disponible bajo cualquier circunstancia. El método Supports devuelve simplemente si el proveedor puede admitir la funcionalidad especificada, dando por supuesto que se reúnen determinadas condiciones. Por ejemplo, el método Supports puede indicar que un objeto Recordset admite actualizaciones aunque el cursor se base en una unión de múltiples tablas, de las que algunas columnas no son actualizables.

 

El valor devuelto por el método Supports dependerá del tipo de recordset elegido. En la siguiente tabla puede ver el tipo de recordset y las constantes para las que va a devolver True:

 

AdOpenForwardOnly   Ninguna

AdOpenKeyset             adBookmark, adHoldRecords, adMovePrevious, adResync

AdOpenDynamic          AdMovePrevious

AdOpenStatic              adBookmark, adHoldRecords, adMovePrevious, adResync

 

 

Método Open

Es el método que ABRE el recordset. Este método es el que busca los registros que han de rellenar el recordset.

 

Sintaxis.  Esta es la sintaxis general:

 

MiRecordset.Open Source, ActiveConnection, CursorType, LockType, Options

 

Un recordset puede abrirse partiendo de una conexión ya abierta. Pero también puede crearse directamente, sin abrir previamente la conexión. Al final, deberá aportar todos los datos necesarios para determinar en que base de datos se abre ese recordset. Sobre que tabla, consulta o sentencia SQL.,  que tipo de cursor va a ser, etc. Lo que ocurre es que ADO es muy flexible y nos permite hacerlo de varias formas, aunque todas ellas conducen a lo mismo.

 

Source (Opcional) Es el nombre de una tabla, consulta o sentencia SQL de la cual se obtienen los registros del Recordset.

 

ActiveConnection (Opcional). Es el nombre de un objeto Connection abierto o una cadena de conexión válida. Esta cadena es la misma que la que emplearíamos para abrir el objeto Connection.

 

CursorType (Opcional).  Un valor que determina el tipo de cursor que el proveedor debe usar al abrir el Recordset. Puede ser una de las siguientes constantes

 

AdOpenForwardOnly   (Predeterminado) Abre un cursor de tipo sólo avance.

AdOpenKeyset             Abre un cursor de tipo conjunto de claves.

AdOpenDynamic          Abre un cursor de tipo dinámico. (Igual que el Dynaset de                                                 DAO)

AdOpenStatic              Abre un cursor de tipo estático.

 

LockType (Opcional). Un valor que determina el tipo de bloqueo que debe usar el proveedor al abrir el Recordset. Con este parámetro se le indica también si debe hacer las actualizaciones registro a registro o en bloque. Puede ser una de las siguientes constantes

 

AdLockReadOnly         (Predeterminado) Sólo lectura. No puede modificar los datos.

AdLockPessimistic       Bloqueo pesimista, registro a registro. El proveedor hace lo                                               necesario para asegurar una modificación correcta de los                                      registros, normalmente   bloqueando registros en el origen de                                                 datos inmediatamente antes de la modificación.

AdLockOptimistic         Bloqueo optimista, registro a registro. El proveedor usa     bloqueooptimista, bloqueando registros sólo cuando se llama al            método Update.

AdLockBatchOptimistic  Actualizaciones optimistas por lotes. Requeridas en el                                                          modo de actualización por lotes en oposición al modo                                                          de actualización inmediata. (Actualización en bloque)

Options (Opcional). Constante que determina como va a evaluar el proveedor de datos el argumento Source. Puede ser una de las siguientes constantes de esta lista.

 

AdCmdText      Indica que el proveedor debe evaluar Source como una definición                          textual de un comando.

AdCmdTable    Indica que ADO debe generar una consulta SQL para devolver                                           todaslas filas de la tabla nombrada en Source.

AdCmdTableDirect      Indica que el proveedor debe devolver todas las filas de la                                      tabla nombrada en Source.

AdCmdStoredProc       Indica que el proveedor debe evaluar Source como un                                                       procedimiento almacenado

AdCmdUnknown          Indica que el tipo de comando del argumento Source es                                       desconocido.

AdCmdFile                   Indica que el Recordset guardado se debe restaurar desde el                                           archivo nombrado en Source.

AdAsyncExecute          Indica que Source se debe ejecutar de forma asíncrona.

AdAsyncFetch              Indica que, tras alcanzar la cantidad inicial especificada en la        propiedad Initial Fetch Size, las filas restantes deben             buscarse de forma asíncrona. Si se requiere una fila que no se      ha encontrado, se bloqueará el subproceso principal hasta que          se disponga de la fila solicitada. 

AdAsyncFetchNonBlocking      Indica que el subproceso principal nunca se bloquea                                                         durante la búsqueda. Si no se encuentra la fila                                                                 solicitada, la fila actual se desplaza automáticamente                                                         al final del archivo.

 

Habrá observado que hemos remarcado que el método Open ABRE un recordset. No lo crea. El recordset debe estar creado previamente. ¿Qué cuando se crea? Mediante la instrucción:

                                    Set MiRecordset = New ADODB.Recordset

 

Metodo Requery

Actualiza los datos de un objeto Recordset volviendo a ejecutar la consulta utilizada para abrirlo. Se obtiene el mismo resultado que si se cerrara el recordset y se volviera a abrir.

 

Sintaxis                        MiRecordset.Requery Opciones

 

Optiones Opcional. Máscara de bits que indica opciones que afectan a esta operación. Si el valor de este parámetro está establecido a adAsyncExecute, esta operación se ejecutará de forma asíncrona y se emitirá un evento RecordsetChangeComplete cuando concluya.

 

Método Resync

Actualiza los datos del objeto Recordset actual.  Este método, a diferencia del método Requery, no vuelve a ejecutar el comando de creación del recordset, sino que lee los registros existentes en el recordset para actualizar su valor, pero no presenta aquellos registros que hubieran sido creados con posterioridad a la apertura del recordset.  Es más rápido que el método Requery, y en muchos casos solamente nos interesa actualizar los registros sobre los que estamos trabajando.

 

Sintaxis            MiRecordset.Resync AffectRecords, ResyncValues

 

Los parámetros AffectRecords   y ResyncValues determinan que registros se van a volver a leer y sobreescribir. Vea la ayuda para mas detalles.        

 

METODO AddNew

Crea un nuevo registro en un objeto Recordset actualizable.

 

Sintaxis                        NombreDelRecordset.AddNew FieldList, Values

 

Los parámetros FieldList y Values son opcionales. En caso de ponerlos, FieldList serán los nombres de los campos a los que se les va a poner un valor, y Values son los valores de cada uno de estos campos. El orden nombre - valor debe mantenerse estrictamente.

 

Siempre recomendaré que, en vez de meter los datos mediante estos parámetros, se metan posteriormente linera a línea, tal como se hizo siempre con los recordsets

 

            NombreDelRecordset!NombredelCampo = ValorDelCampo

ó

            NombreDelRecordset(“NombredelCampo”) = ValorDelCampo

 

Esta segunda forma es necesaria cuando el nombre del campo tiene espacios. Nunca es recomendable poner espacios en los nombres de campos, pero en caso de que existan, debe optar por utilizar la sintaxis segunda, con los paréntesis y comillas dobles.

 

No siempre se puede utilizar el método AddNew. Puede comprobar si se puede utilizar, usando el método Supports visto anteriormente.

 

El método AddNew convierte a este registro recién creado en registro actual. Pero este registro solamente existe en el recordset. Para introducir los datos en la base de datos, (Y por lo tanto en el disco duro) es necesario invocar el método Update una vez introducidos todos los valores de los campos que deseamos introducir. Con algún tipo de cursor es necesario también utilizar el método Requery para poder acceder al registro recién creado.

 

Si se invoca el método AddNew mientras se está editando el registro actual, o durante otra operación AddNew, ADO invoca automáticamente el método Update para guardar los cambios.  Vea más adelante los métodos Update y UpdateBatch.

 

Método Update

Guarda los cambios realizados en el registro actual de un objeto Recordset. Se utiliza tanto para “rematar” una operación de creación de un registro iniciada con AddNew, como para guardar los nuevos datos del registro actual (Recuerde que en ADO no existe el método Edit, tal como ocurría en DAO)

.

Sintaxis                        NombreDelRecordset.Update Fields, Values

 

En esta sintaxis, Fields y Values son opcionales, y solamente tienen aplicación cuando se trata de cambiar los valores del registro actual, no de terminar una operación de creación de un nuevo registro mediante AddNew.

 

Vuelvo a recomendar lo anterior. Para cambiar los valores de varios campos de un registro, nos colocaremos sobre ese registro, y sin invocar ningún método, ejecutaremos este código

 

            MiRecordset!Campo1 = Valor1

            MiRecordset!Campo2 = Valor2

            ……….

            MiRecordset!CampoN = ValorN

            MiRecordset.Update

 

Pero en ADO pasa una cosa que no pasaba en DAO. Si cambiamos de registro una vez modificado el valor de un registro, ADO invoca automáticamente el método Update. Por lo tanto, el código siguiente:

 

            MiRecordset!Campo1 = Valor1

            MiRecordset!Campo2 = Valor2

            ……….

            MiRecordset!CampoN = ValorN

 

Tendrá el mismo resultado que el anterior cuando cambiemos de registro actual. Esto puede ser bueno a malo, pero personalmente pienso que no es práctico porque implica tener mucho más cuidado que en DAO. Hace lo mismo que cuando tenemos unos controles enlazados a datos mediante un control Data.

 

Si una vez que ejecutamos una línea tal como esta

           

            MiRecordset!Campo1 = Valor1

 

Queremos que ese nuevo valor no entre en la base de datos, debemos cancelarlo mediante el método CancelUpdate.

 

Método UpdateBatch

Escribe en disco todas las actualizaciones pendientes de proceso por lotes.  En ADO un recordset puede actualizarse registro a registro o por lotes. Todo dependerá de cómo se ha abierto  (Si el valor LockType se ha puesto a AdLockBatchOptimistic)

 

Sintaxis                       MiRecordset.UpdateBatch AffectRecords

 

AffectRecords Constante que determina a cuántos registros afectará el método                                         UpdateBatch. Puede tomar uno de los siguientes valores.

 

            AdAffectCurrent           Escribe solamente los cambios pendientes en el                                                  registro actual.

            AdAffectGroup             Escribe los cambios pendientes que cumplen el valor                                                       de la propiedad Filter.

            AdAffectAll                   (Predeterminado) Escribe los cambios pendientes en                                                        todos los registros del objeto Recordset.

           

Método Cancel

Cancela la ejecución del método Open.

 

Sintaxis           NombreDelRecordset.Cancel

 

El método Cancel solamente puede usarse si el método Open fue invocado con la opción adAsyncConnect, adAsyncExecute o adAsyncFetch.

 

 

Método Delete

Elimina el registro actual o un grupo de registros. Por defecto elimina solamente el registro actual. Vea la ayuda para ampliar los detalles respecto al parámetro opcional AffectRecords

 

Sintaxis                       MiRecordset.Delete AffectRecords

 

Método CancelUpdate

Habíamos visto más atrás que el ADO no existe el método Edit. Para modificar un registro basta con poner una instrucción tal como esta:

 

            MiRecordset!MiCampo = MiNuevoValor

 

Y a continuación rematar la operación mediante el método Update

 

            MiRecordset.Update

 

Si por cualquier circunstancia se ha ejecutado la primera instrucción, y luego queremos volvernos atrás, antes de ejecutar el método Update debemos deshacer el cambio con el método CancelUpdate, con lo que el registro afectado recuperará nuevamente su valor original.

 

Sintaxis                                    MiRecordset.CancelUpdate

 

Recuerde que ADO funciona de forma distinta a DAO con estos métodos de modificación de los registros. Recuerde que si está en proceso de modificación de un registro (Ha ejecutado la primera línea del ejemplo anterior) y cambia de registro, por el hecho de cambiar de registro, ADO invoca automáticamente el método Update.

 

 

Método CancelBatch

Cancela una actualización por lotes pendiente. Es similar a la anterior, pero para actualización por lotes.

 

Sintaxis                        MiRecordset.CancelBatch AffectRecords

 

Método Clone

Crea un objeto Recordset duplicado a partir de un objeto Recordset existente. Opcionalmente, puede especificarse que el nuevo recordset sea solamente de lectura

 

Sintaxis           Set rstDuplicate = rstOriginal.Clone (LockType)

 

(El objeto rstDuplicate debe estar declarado previamente como objeto ADODB.Recordset)

 

LockType puede tomar uno de los siguientes valores:

 

AdLockUnspecified      (Predeterminado) El recordset resultante tendrá el mismo tipo de                           bloqueo que el original.

AdLockReadOnly         El recordset creado es solamente de lectura.

 

El recordset resultante del método Clone, aunque igual al original en el momento de su creación, es completamente independiente de este a partir de ese momento, por lo que las actualizaciones efectuadas en el original no afectan al clonado.

 

Método Move

Mueve la posición del registro actual de un objeto Recordset

.

Sintaxis                                    MiRrecordset.Move NumRecords, Start

 

NumRecords    Un valor  Long con signo que especifica el número de registros que debe moverse a partir de la posición del registro actual o del registro especificado en el parámetro Start,  si es que se especifica.

 

Start Opcional. Un String o Variant cuyo resultado sea un marcador del tipo Bookmark.  Puede utilizar también una de las siguientes constantes:

 

            AdBookmarkCurrent    (Predeterminado) Cuenta a partir del registro actual

            AdBookmarkFirst         Cuenta a partir del primer registro

            AdBookmarkLast         Cuenta a partir del último registro

 

Métodos MoveFirst, MoveLast, MoveNext y MovePrevious

Pasa al primer, último, siguiente o anterior registro de un objeto Recordset especificado y lo convierte en el registro actual. Funciona igual que en DAO

 

Tenga en cuenta a la hora de usar los métodos Move que pueden existir Recordsets que no permiten el movimiento hacia atrás.

Método Find

Busca el primer registro del recordset que satisfaga los criterios especificados en el criterio de búsqueda. Si se cumple el criterio de búsqueda, la posición del recordset se establece en el primer registro encontrado; si no, la posición se establece al final del recordset.

 

Sintaxis           MiRecordset.Find (criterio, SkipRows, searchDirection, start)

 

criterio             Es el criterio de búsqueda. Por ejemplo  “Pais = España”  siendo Pais el nombre del campo en el cual buscamos el valor España

 

SkipRows         (Opciopnal) Es un Long, cuyo valor predeterminado es cero, que especifica el número de registros a partir del registro actual donde debe empezar la búsqueda.

 

searchDirection  (Opcional) Un valor que especifica si la búsqueda se realiza en dirección al final del recordset (adSearchForward) o en dirección hacia el principio del recordset (adSearchBackward). La búsqueda termina al final o al principio del recordset, dependiendo del valor de searchDirection.

 

start                  (Opcional) Un marcador tipo BookMark que se utiliza como posición inicial de la búsqueda.

 

El operador de comparación de criterio puede ser ">",  "<", "=", ">=" , "<=", "<>" (distinto de) o "like" (coincidencia parcial de cadenas).  El valor de comparación puede ser una cadena, un número en coma flotante o una fecha. Los valores de cadena están delimitados con comillas sencillas (por ejemplo, "Pais = 'España'"). Los valores de fecha están delimitados con signos "#" y con formato mm/dd/yy (por ejemplo, "fecha_inicial > #7/22/97#"). Si el operador de comparación es "like", el valor de la cadena puede contener los caracteres comodín "*" o "_". (Funcionan de forma idéntica, sustituyendo a cualquier sucesión de caracteres.) No acepta el carácter “?” (Por ejemplo, "Pais like ‘Es_’" o “Pais Like ‘Es*’ encuentra España y Estonia)

 

ADO no tiene los métodos FindFirst, FindNext, FindPrevious y FindLast.  Deberá emplear el método Find de forma inteligente para implementar estos otros.

 

Método Save

Este método permite guardar el contenido de un Recordset en un fichero. Puede ser muy útil cuando queremos exportar ese recordset hacia otra aplicación.

 

Sintaxis                        MiRecordset.Save FileName, PersistFormat

 

FileName es la ruta completa del fichero en el que se guardará el Recordset.

PersistFormat (Opcional). Un valor que especifica el formato en que se guardará el             Recordset. Puede ser una de las constantes siguientes.

 

AdPersistADTG            (Valor predeterminado) Se guarda en un formato propietario                                               (Advanced Data Tablegram). No es inteligible a simple vista,                                              pero genera ficheros bastante cortos.

 

AAdPersistXML            Se guarda en formato XML. Es un formato puramente en ASCII                                          donde pueden verse los nombres de los campos y su                                                       contenido. Este formato genera ficheros más grandes que el                                             ADT

Si el recordset tienen aplicado un filtro (Mediante la propiedad Filter) solamente guarda los registros que deja ver ese filtro.

 

Si ya existe el fichero le dará un error. Cerciórese que no existe (Mediante la función Dir) y bórrelo antes de volver a utilizar el método Save.

 

Método Seek

Este método busca un registro desplazándose por el recordset a lo largo de un índice o un conjunto de índices.  La búsqueda mediante Seek es mucho más rápida que con Find, ya que la realiza siguiendo el ordenamiento de los registros según un índice.

 

Para poder usar el método Index es necesario que el proveedor acepte índices en el objeto recordset.  Esto ha llevado al autor a no poder presentar ningún ejemplo de este método, ya que todas las bases de datos ensayadas no permitían índices. Puede ver si acepta índices mediante el método Supports:

 

                        If MiRecordset1.Supports(adIndex) = True Then

 

Vea la ayuda de VB para mayor información

 

Método NextRecordset

Para entender este método es necesario explicar previamente como se puede crear un recordset compuesto.

 

Un recordset compuesto es un recordset que se crea concatenando sentencias SELECT, y cada una de ellas creará, dentro del mismo Recordset, un recordset particular. Al crear el recordset, el recordset particular que va a estar activo es el correspondiente a la primera sentencia SELECT. Mediante el método NextRecordset podemos ir avanzando a través de los siguientes recordsets particulares.  El carácter de separación entre las sentencias SELECT es el punto y coma ( ; )

 

 

MiRecordset1.Open "Select * From Regimenes; Select * From Regimen_Seguimiento Where Rs_Origen = 'LSB'", MiConexionADO, adOpenDynamic, adLockOptimistic

 

(La instrucción anterior debe leerse como una sola línea)

 

MiRecordset es un recordset compuesto. Toma datos de dos tablas distintas, pero podría haberlo hecho solamente de una tabla con una condición distinta en la SELECT.

 

Cuando se ejecuta esa línea, el recordset actual es el correspondiente a la primera selección. (Select * From Regimenes).  Ejecutando el método NextRecordset ese recordset primero se borra y pasa a ser recordset actual el creado con la selección segunda (Select * From Regimen_Seguimiento Where Rs_Origen = 'LSB'")

 

            Set MiRecordset1 = MiRecordset1.NextRecordset

 

Puede usar también este recordset para crear un nuevo recordset a partir del primero

 

            Set MiRecordset2 = MiRecordset1.NextRecordset

 

MiRecordset2 debe estar declarado como objeto recordset, y creado con la instrucción New:

            Set MiRecordset2 = New ADOBD.Recodset

 

 

 

La colección Fields de un recordset ADO

 


Contiene todos los objetos Field de un objeto Recordset.

 

 


Un objeto Recordset tiene una colección Fields que contiene todos los objetos Field. Cada objeto Field se corresponde a una columna del Recordset.

 

Vamos a ver aquí un truco que nos permite ADO. Podemos crear un recordset ¡Sin necesidad de una base de datos!

 

Cuando estudiamos el objeto recordset vimos que el recordset se crea con una instrucción como esta:       

            Set MiRecordset1 = New ADODB.Recordset

 

Ahora ya podemos abrir el recordset leyendo los datos desde una base de datos. Utilizamos para ello el método Open del recordset:

 

MiRecordset1.Open "Select * From Regimenes", MiConexionADO, adOpenDynamic, adLockOptimistic

 

Mediante el método Open lo que hace el recordset es conocer su estructura (Que campos tiene, propiedades de estos campos, etc) y el valor de cada uno de los campos de sus registros.  ¿Qué pasaría si en vez de abrir el recordset le vamos añadiendo objetos Field a su colección Fields?  Lo hacemos mediante el método Append:

 

MiRecordset1.Fields.Append "MiCampo1", adBigInt

MiRecordset1.Fields.Append "MiCampo2", adChar, 25

MiRecordset1.Fields.Append "MiCampo3", adBSTR

 

Lo que ocurre es que el recordset ya tiene tres campos, el primero de nombre MiCampo1, numérico Long, el segundo, un string de 25 caracteres de nombre MiCampo2, y el tercero, de nombre MiCampo3, una cadena de caracteres de longitud indefinida, terminada en un carácter nulo.  Ya tenemos una estructura de un recordset sin necesidad de haber leído la base de datos. No es necesario por lo tanto que exista una tabla o consulta almacenada con esa estructura. Ahora podemos abrir el recordset:

 

MiRecordset1.Open

 

Lo abrimos sin pasarle ningún parámetro. Ahora ya está abierto y podemos trabajar con el como con un recordset cualquiera. Recuerde que al principio está vacío.

 

MiRecordset1.AddNew

MiRecordset1!MiCampo1 = 34

MiRecordset1!MiCampo2 = "Guía del Estudiante"

MiRecordset1!MiCampo3 = "Hola mi amor" & vbCrLf & "Yo soy tu lobo"

MiRecordset1.Update

 

Ya tenemos un registro dentro del recordset. Podemos introducirle tantos registros como queramos, y luego movernos por el recordset mediante los métodos Movexxxx. Ahora podremos leer el contenido del registro actual:

 

Label1 = MiRecordset1!MiCampo1

Label2 = MiRecordset1!MiCampo2

Label3 = MiRecordset1!MiCampo3

El resultado del código de el ejemplo se traducirá en algo como esto:


 


Y ahora vienen lo mejor. ¿Para que queremos un recordset que no tienen datos leídos desde una base de datos?  Las aplicaciones de esto solamente está limitadas por la imaginación. Pienso, por ejemplo, en introducir en un recordset todos los datos leídos de un fichero de configuración, y así tener todos esos datos disponibles durante toda la aplicación, en vez de en variables,  como        MiRecordset!MiDato1

 

Es una idea, pero piense que esto no regala nada. El espacio de memoria consumido será similar a si usa variables. Pero posiblemente estará más cómodo y más inteligible su código.

 

Veamos los métodos de la colección Fields

 

Método Append

Agrega un campo a una colección Fields de un Recoprdset.

 

Sintaxis                        MiRecordset.Fields.Append Name, Type, DefinedSize, Attrib

 

Name   Un String con el nombre del nuevo objeto Field, que tiene que ser único dentro de la coleccón Fields.

 

Type     Tipo de datos que va a contener ese campo. Puede tomar uno de estos valores:

 

adArray

Se une en una instrucción OR lógica con otro tipo para indicar que los datos son una matriz segura de ese tipo (DBTYPE_ARRAY).

adBigInt

Un entero con signo de 8 bytes (DBTYPE_I8).

adBinary

Un valor binario (DBTYPE_BYTES).

adBoolean

Un valor Boolean (DBTYPE_BOOL).

adByRef

Se une en una instrucción OR lógica con otro tipo para indicar que los datos son un puntero a los datos del otro tipo (DBTYPE_BYREF).

adBSTR

Una cadena de caracteres terminada en nulo (Unicode) (DBTYPE_BSTR).

adChar

Un valor de tipo String (DBTYPE_STR).

adCurrency

Un valor de tipo Currency (DBTYPE_CY). Un valor Currency es un número de coma fija con cuatro dígitos a la derecha del signo decimal. Se almacena en un entero con signo de 8 bytes en escala de 10.000.

adDate

Un valor de tipo Date (DBTYPE_DATE). Un valor Date se almacena como un valor de tipo Double; la parte entera es el número de días transcurridos desde el 30 de diciembre de 1899 y la parte fraccionaria es la fracción de un día.

adDBDate

Un valor de fecha (aaaammdd) (DBTYPE_DBDATE).

adDBTime

Un valor de hora (hhmmss) (DBTYPE_DBTIME).

adDBTimeStamp

Una marca de fecha y hora (aaaammddhhmmss más una fracción de miles de millones) (DBTYPE_DBTIMESTAMP).

adDecimal

Un valor numérico exacto con una precisión y una escala fijas (DBTYPE_DECIMAL).

adDouble

Un valor de coma flotante de doble precisión (DBTYPE_R8).

adEmpty

No se ha especificado ningún valor (DBTYPE_EMPTY).

adError

Un código de error de 32 bits (DBTYPE_ERROR).

adGUID

Un identificador único global (GUID) (DBTYPE_GUID).

adIDispatch

Un puntero a una interfaz Idispatch de un objeto OLE (DBTYPE_IDISPATCH).

adInteger

Un entero firmado de 4 bytes (DBTYPE_I4).

adIUnknown

Un puntero a una interfaz Iunknown de un objeto OLE (DBTYPE_IUNKNOWN).

adLongVarBinary

Un valor binario largo (sólo para el objeto Parameter).

adLongVarChar

Un valor largo de tipo String (sólo para el objeto Parameter).

adLongVarWChar

Un valor largo de tipo String terminado en nulo (sólo para el objeto Parameter).

adNumeric

Un valor numérico exacto con una precisión y una escala exactas (DBTYPE_NUMERIC).

adSingle

Un valor de coma flotante de simple precisión (DBTYPE_R4).

adSmallInt

Un entero con signo de 2 bytes (DBTYPE_I2).

adTinyInt

Un entero con signo de 1 byte (DBTYPE_I1).

adUnsignedBigInt

Un entero sin signo de 8 bytes (DBTYPE_UI8).

adUnsignedInt

Un entero sin signo de 4 bytes (DBTYPE_UI4).

adUnsignedSmallInt

Un entero sin signo de 2 bytes (DBTYPE_UI2).

adUnsignedTinyInt

Un entero sin signo de 1 byte (DBTYPE_UI1).

adUserDefined

Una variable definida por el usuario (DBTYPE_UDT).

adVarBinary

Un valor binario (sólo para el objeto Parameter).

adVarChar

Un valor de tipo String (sólo para el objeto Parameter).

adVariant

Un tipo Variant de automatización (DBTYPE_VARIANT).

adVector

Se une en una instrucción OR lógica con otro tipo para indicar que los datos son una estructura DBVECTOR, tal como está definida por OLE DB, que contiene un contador de elementos y un puntero a los datos del otro tipo (DBTYPE_VECTOR).

adVarWChar

Una cadena de caracteres Unicode terminada en nulo (sólo para el objeto Parameter).

adWChar

Una cadena de caracteres Unicode terminada en nulo (DBTYPE_WSTR).

 

 

DefinedSize      Un Long que define el tamaño del campo si fuese necesario. (Por ejemplo para un string)

 

Attrib               (Opcional). Especifica los atributos del campo a añadir.  Puede tomar estos valores:

 

adFldMayDefer

Indica que el campo se aplaza, es decir, los valores del campo no se recuperan del origen de datos con todo el registro, sino solamente cuando se tiene acceso explícito a los mismos.

adFldUpdatable

Indica que se puede escribir en el campo.

adFldUnknownUpdatable

Indica que el proveedor no puede determinar si se puede escribir en el campo.

adFldFixed

Indica que el campo contiene datos de longitud fija.

adFldIsNullable

Indica que el campo acepta valores Null.

adFldMayBeNull

Indica que se pueden leer valores Null del campo.

adFldLong

Indica que se trata de un campo binario largo. También indica que se pueden utilizar los métodos AppendChunk y GetChunk.

adFldRowID

Indica que el campo contiene un identificador de fila persistente en el que no se puede escribir y que no tiene ningún valor significativo excepto la identificación de la fila (como por ejemplo un número de registro, un identificador único, etc.).

adFldRowVersion

Indica que el campo contiene algún tipo de marca de hora o de fecha que se utiliza para efectuar actualizaciones.

adFldCacheDeferred

Indica que el proveedor almacena los valores del campo en la memoria caché y que las lecturas siguientes se efectúan en dicha memoria .



Método Delete

Teóricamente elimina un objeto de la colección Fields.

 

Sintaxis                        Fields.Delete Field

 

Field        Un Variant que designa el objeto Field que se va a eliminar. Este parámetro tiene que ser el nombre del objeto Field; no puede ser una posición ordinal o el propio objeto Field.

Comentarios

La llamada al método Fields.Delete en un Recordset abierto provoca un error de ejecución.

 

(Como ha ocurrido en otras ocasiones, al autor le ha sido imposible ejecutar este método con los resultados esperados)

 

Método Item

 

Sintaxis            MiRecordset.Fields.Item (Index)

 

Devuelve el elemento de la colección Fields especificado en el índice. Devuelve el objeto, por lo tanto, y sobre ese objeto, podemos obtener las propiedades que deseemos. En el ejemplo siguiente, introducimos los nombres de todos los campos en un ComboBox llamado ComboCampos

 

Dim MM As String, I As Integer

For I = 0 To MiRecordset1.Fields.Count - 1

MM = MiRecordset1.Fields.Item(I).Name

ComboCampos.AddItem MM

Next I

 

Método Refresh

Aunque la colección Fields tiene este método, la verdad es que no tienen efectos visibles sobre esa colección.

 

Propiedades de la colección Fields

 

Propiedad Count

Devuelve el número de campos de la colección Fields. Es un Long.

 

 


 

 


El Objeto Command

 

Un objeto Command es la definición de un comando específico que se piensa ejecutar contra un origen de datos.  Mediante un objeto Command podemos crear un recordset, pero recuerde que un recordset lo podemos también crear directamente.

 

Utilice un objeto Command para consultar una base de datos y obtener registros en un objeto Recordset, para añadir o eliminar registros, ejecutar una operación de manejo masivo de datos o para manipular la estructura de una base de datos.

 

Propiedades del Objeto Command

 

Propiedad ActiveConnection

Indica a qué objeto Connection pertenece actualmente el objeto Command. Es un string con el nombre de la conexión.

 

Propiedad CommandText

Contiene el texto del comando que se quiere emitir al proveedor. Es un string. Suele ser una instrucción SQL, un nombre de tabla o un procedimiento almacenado, o cualquier otra instrucción que reconozca el proveedor. El valor predeterminado es una cadena vacía.

Propiedad CommandTimeout

Especifica el intervalo de espera para que se ejecute un comando antes de que finalice el intento y se genere un error. Es un Long que indica en segundos ese tiempo. El valor predeterminado es 30.

 

Propiedad CommandType       (IMPORTANTE)

Indica el tipo de un objeto Command. Esta propiedad se usa para optimizar la evaluación de la propiedad CommandText, ya que de esta forma el proveedor no tiene que perder tiempo examinando si es una instrucción SQL, un procedimiento almacenado o un nombre de tabla. Si  el valor de esta propiedad es adCmdUnknown (valor predeterminado), estamos forzando al proveedor a que realice esa investigación lo que provocará probablemente un descenso en su rendimiento. Si sabe qué tipo de comando está usando, el establecimiento de la propiedad CommandType instruye a ADO a que vaya directamente al código relevante. Si la propiedad CommandType no coincide con el tipo de comando de la propiedad CommandText, ocurre un error cuando llama al método Execute.

 

Valores posibles

 

AdCmdText                  Indica que es una definición textual de un comando o una llamada a un                              procedimiento almacenado.

 

AdCmdTable                Indica que es un nombre de tabla cuyas columnas se devuelven todas                               mediante una consulta SQL generada internamente.

 

AdCmdTableDirect      Indica que es un nombre de tabla en la que se devuelven todas las                                    columnas.

 

AdCmdStoredProc       Indica que es un nombre de procedimiento almacenado

 

AdCmdUnknown          Predeterminado. El tipo de comando de la propiedad CommandText                                es desconocido.

 

AdCmdFile                   Evalúa CommandText como el nombre de archivo de un valor                                          Recordset persistente.

 

AdExecuteNoRecords  Indica que es un comando o un procedimiento almacenado que no devuelve filas (por ejemplo, un comando que sólo inserta datos). Si se recupera alguna fila, se descarta y no se devuelve. Siempre se combina con adCmdText o adCmdStoredProc.

 

Propiedad Prepared

Es un Booleano que indica si se debe guardar una versión compilada de un comando antes de su ejecución. Esta propiedad fuerza al proveedor a guardar una versión preparada (compilada) de la consulta especificada en la propiedad CommandText antes de la primera ejecución de un objeto Command. Esto puede disminuir el rendimiento de la primera ejecución de un comando, pero cuando el proveedor haya compilado el comando, utilizará la versión compilada del mismo para las ejecuciones siguientes, lo cual aumentará el rendimiento.

Si el proveedor no admite la preparación del comando, puede devolver un error cuando esta propiedad se establezca a True. Si no devuelve un error, simplemente ignora la solicitud de preparar el comando y establece la propiedad Prepared a False.

 

Propiedad State

Describe el estado del objeto: abierto o cerrado. Devuelve un Long o una constante: adStateClosed o adStateOpen

 

 

Métodos del Objeto Command

 

Método Execute    (IMPORTANTE, más bien diríamos, el objetivo del Command)

Ejecuta la consulta, la instrucción SQL o el procedimiento almacenado especificado en la propiedad CommandText.  Devuelve un recordset o modifica la base de datos.

 

Sintaxis                       

Para un Command que devuelva filas:

 

Set recordset = command.Execute(RecordsAffected, Parameters, Options)

 

Para un Command que no devuelva filas:

 

command.Execute RecordsAffected, Parameters, Options

 

command es el nombre del Objeto Command

 

RecordsAffected Opcional. Una variable Long en la que el proveedor devuelve el número de registros afectados por la operación.

 

Parameters Opcional. Una matriz Variant con los valores de los parámetros pasados con una instrucción SQL. (Los parámetros de salida no devuelven valores correctos cuando se pasan en este argumento).

 

Options Opcional. Un valor Long o una constante. Acepta estos valores

 

adCmdText                  Indica que el proveedor tiene que evaluar CommandText como                   definición textual de un comando, como una instrucción SQL.

adCmdTable                Indica que ADO tiene que generar una consulta SQL para devolver                         todas las filas de la tabla mencionada en CommandText.

adCmdTableDirect       Indica que el proveedor tiene que devolver todas las filas de la tabla                                    mencionada en CommandText.

AdCmdStoredProc       Indica que el proveedor tiene que evaluar CommandText como                                          procedimiento almacenado.

adCmdUnknown          Indica que el tipo de comando en CommandText es desconocido.

adAsyncExecute          Indica que el comando se tiene que ejecutar de forma asíncrona.

adAsyncFetch Indica que el resto de las filas siguientes a la cantidad inicial especificada en la                  propiedad CacheSize tiene que ser recuperada de forma asíncrona.

 

Método Cancel

Cancela la ejecución de una llamada asíncrona pendiente al método Execute

 

Sintaxis                        NombredelObjetoCommand.Cancel

 

Utilice el método Cancel para terminar la ejecución de una llamada asíncrona a un método Execute (es decir, el método fue invocado con la opción adAsyncExecute o adAsyncFetch).

 

 

Comandos parametrizados.

 

Los objetos Command pueden utilizar parámetros. De esta forma, podemos construir una consulta utilizando la interrogación (?) como comodín. Así cada vez que ejecutemos el comando, V.B. se encargará de sustituir el comodín por los parámetros asociados a dicho command. Además podemos utilizar los parámetros para recoger los valores devueltos por un Procedimiento almacenado en la base de datos. Para entender mejor este tipo de consultas primero veremos qué es el objeto parameter.

 

Ejemplo de la utilización de Command

 

Veamos un ejemplo de cómo usar el Objeto Command. Pero previamente vamos a ver un código del que hemos partido para hacer ver al alumno que ADO permite hacer las cosas de muchas maneras. Este código mete los datos de un documento en una base de datos Oracle, leyendo previamente el número más alto del documento para poner al nuevo documento un número igual al último + 1.:

 

Declaraciones

Dim ConexBDPrensa As ADODB.Connection

Dim RsBDPrensa1 As ADODB.Recordset

Dim StrIntroducir As String, NumeroDocumento as long

 

Rem Se abre un objeto Connection para crear sobre él el recordset

Set ConexBDPrensa = New ADODB.Connection

ConexBDPrensa.ConnectionString = "Provider=MSDAORA.1;”  & _

“User ID=INTRANET;Password=INTRANET;Data Source=intranet;” & _

“Persist Security Info=False"

ConexBDPrensa.Open

 

 

Rem Se abre un recordset para leer el número, se lee y se vuelve a cerrar

RsBDPrensa1.Open "Int_Documentos Order By CL_DOC", ConexBDPrensa, adOpenDynamic, adLockOptimistic

RsBDPrensa1.MoveLast

NumeroDocumento = RsBDPrensa1!CL_DOC

NumeroDocumento = NumeroDocumento + 1

RsBDPrensa1.Close

 

(*  Este es el punto donde cambia el código que verá más adelante)

 

Rem  Se introduce en una variable tipo String una instrucción para añadir un nuevo registro

Rem  Esa instrucción se va a ejecutar desde el objeto Connection mediante su método Execute

 

 

StrIntroducir = "Insert Into INT_DOCUMENTOS " & _

"(CL_DOC,NOM_DOC,TITULO_DOC,AUTOR_DOC,CL_TEMA_DOC,CL_DPT_DOC,” & _

“CL_TIPO_DOC,FICH_DOC,FECHA_EMISION_DOC,ULTIMA_HORA_DOC,” & _

VISIBLE_DOC) Values (" & NumeroDocumento & ",'" & TbTitulo & "','" & TbTitulo & _

"','" & TbTitulo.Tag & "',19,2,1,'" & HRefPrensa & "/" & TbNombFichTIF & "','" & Date & "',0,1)"

 

Rem Observe que los valores tipo string introducidos (TbXXX) van entre comilla simple

Rem  Se ejecuta esa instrucción desde el objeto Connection ConexBDPrensa

 

ConexBDPrensa.Execute StrIntroducir

 

Rem Se cierra el Objeto Connection

 

ConexBDPrensa.Close

Rem Aquí termina la operación de crear un nuevo registro

MsgBox "Documento enviado"

 

Este es el código real de una aplicación que introduce los datos el resumen de prensa diario en una base de datos. Se introduce un nuevo registro en la tabla INT_DOCUMENTOS. El resumen de prensa es un fichero .Tiff  de nombre TbNombFichTIF que se mete en una carpeta del servidor mediante FTP, y para su loccalización y presentación en una página Web es necesario introducir su nombre y Path y otros datos en una base de datos.  Los campos que se introducen y los valores de cada uno son:

 

Campo                          Valor

 

CL_DOC,                      NumeroDocumento        (Long calculado)

NOM_DOC                    TbTitulo             (String contenido en TbTitulo.Text)

TITULO_DOC                 TbTitulo             (String contenido en TbTitulo.Text – se repite-)

AUTOR_DOC                TbTitulo.Tag                   (String contenido en TbTitulo.Tag)

CL_TEMA_DOC 19                                 (Integer, dato fijo)

CL_DPT_DOC               2                                  (Integer, dato fijo)

CL_TIPO_DOC              1                                  (Integer, dato fijo)

FICH_DOC                    HRefPrensa & "/" & TbNombFichTIF  Un string que indica el nombre                                  del fichero (TbNombFichTIF.Text) y su carpeta (Variable HrefPrensa)

FECHA_EMISION_DOC Date                 (Fecha actual)

ULTIMA_HORA_DOC     0                                  (Byte, dato fijo)

 VISIBLE_DOC              1                                  (Byte, dato fijo)

 

 

Esta forma de introducir los datos,  método que los lingüistas especializados en la jerga informática llaman “a capón”, es la que nunca falla. Exige un poco de código, con muchas probabilidades de equivocarse, pero muchas veces se prefiere esta forma de meter datos a utilizar el método AddNew.  Tiene la gran ventaja de que la acepta cualquier base de datos, independientemente de donde esté el cursor.  Habrá observado que utilizamos el método Execute del objeto Connection. Y así funciona perfectamente. Vamos a hacer lo mismo, pero introduciendo la cadena de caracteres un objeto Command,  (Que pertenece al mismo objeto Connection sobre el que ahora hemos ejecutado el Execute) y vamos a ejecutar el Execute de ese Command. ¿Se da cuenta que estamos haciendo lo mismo?  El nuevo código creado a partir del anterior es el siguiente:

 

(*  Este es el mismo punto de antes. Aquí comienza el cambio del código)

 

Dim MiComando As ADODB.Command

Set MiComando = New ADODB.Command

MiComando.ActiveConnection = ConexBDPrensa

 

MiComando.CommandText = "Insert Into INT_DOCUMENTOS " _

& "(CL_DOC,NOM_DOC,TITULO_DOC,AUTOR_DOC,CL_TEMA_DOC,CL_DPT_DOC,CL_TIPO_DOC,FICH_DOC,FECHA_EMISION_DOC,ULTIMA_HORA_DOC,VISIBLE_DOC) " _

& "Values (" _

& NumeroDocumento & ",'" & TbTitulo & "','" & TbTitulo & "','" & TbTitulo.Tag & "',19,2,1,'" & HRefPrensa & "/" & TbNombFichTIF & "','" & Date & "',0,1)"

 

MiComando.Execute

ConexBDPrensa.Close

 

ADO le permite hacer las cosas de maneras muy distintas, pero siempre debe aportar la misma información. En este caso ha visto que el objeto Command no hace falta para nada. ¿Entonces, para que existe?  La respuesta es sencilla: facilita la comprensión del código.  Pero que el objeto Command no le perjudique precisamente eso, la comprensión del código. No se preocupe de no ser estrictamente académico. Este humilde autor nunca usa Command excepto para explicarlo.  ADO nos permite eso.

 

Vamos a ver ahora cómo haríamos esto mismo con el método AddNew.

 

Deberemos crear un recordset. Lo primero, lo declaramos:

Dim RsBDPrensa as ADODB.Recodset

 

Luego lo creamos:

Set RsBDPrensa = New ADODB.Recordset

 

Lo abrimos. Pero primero tomamos la precaución de poner la propiedad CursorLocation del Objeto Connection a adUseClient  (Lado cliente) y de esta forma los cursores creados para los recordsets abiertos sobre ese objeto connection estarán del lado cliente. Si el cursor está de lado servidor es posible que no nos deje usar el método AddNew. (Vea Nota 1)

 

ConexBDPrensa.CursorLocation = adUseClient

 

Abrimos el Recordset:

RsBDPrensa.Open "Int_Documentos", ConexBDPrensa, adOpenDynamic, adLockOptimistic

 

Ejecutamos el método AddNew

   RsBDPrensa.AddNew

 

Metemos los datos

   RsBDPrensa!CL_DOC = NumeroDocumento

   RsBDPrensa!NOM_DOC = TbTitulo

   RsBDPrensa!TITULO_DOC = TbTitulo

   RsBDPrensa!AUTOR_DOC = TbTitulo.Tag

   RsBDPrensa!CL_TEMA_DOC = 19

   RsBDPrensa!FECHA_EMISION_DOC = Date

   RsBDPrensa!CL_DPT_DOC = 2

   RsBDPrensa!CL_TIPO_DOC = 1

   RsBDPrensa!FICH_DOC = HRefPrensa & "/" & TbNombFichTIF

   RsBDPrensa!VISIBLE_DOC = 1

   RsBDPrensa!ULTIMA_HORA_DOC = 0

 

Rematamos con el método Update

   RsBDPrensa.Update

 

Cerramos el recordset.  

RsBDPrensa.Close

 

Cerramos la conexión

ConexBDPrensa.Close

 

Nota 1. –  Muchos programadores se rinden cuando ven que no les funciona los métodos AddNew / Update para introducir nuevos datos. Cierto es que cada base de datos se comporta de forma distinta respecto a este método. Pero antes de rendirse y usar el código “a capón” intente ver como tienen la propiedad CursorLocation, el tipo de recordset abierto y el tipo de bloque elegido (Recuerde que por defecto es de solo lectura).  Eso sí, el método “a capón” funciona siempre (Excepto que sea solo lectura), independientemente del bloqueo y del tipo de cursor

 


El “Control Data” de ADO  -  (Adodc  ADO Data Control)

 

Este capítulo parece que quedaba un poco corto. No por el número de páginas, sino porque tanto en DAO como en RDO nos explayamos con el control Data, y en ADO parece que solamente lo hemos visto de pasada para explicar cómo se compone la cadena de conexión. Veámoslo un poco más en profundidad.

 

El control Data para ADO es el “Microsoft ADO data control 6.0 (OLEDB)” que se encuentra en Proyecto | Componentes.  La apariencia es similar a la del Data de DAO

 


 


Hagamos un repaso de sus propiedades. Veremos solamente aquellas que son específicas de ADO:

 

Propiedad BOFAction.

 

Establece la forma de proceder cuando llega a la fila anterior a la primera. Toma uno de estos valores:

 

0 – adDoMoveFirst         Vuelve a la primera fila

1 – adDoStayBOF          Permanece en la fila BOF

 

 

Propiedad CommandType

 

Es idéntica a la misma propiedad del objeto Command. Acepta los valores:

 

AdCmdText                  Indica que es una definición textual de un comando o una llamada a un                              procedimiento almacenado.

 

AdCmdTable                Indica que es un nombre de tabla cuyas columnas se devuelven todas                               mediante una consulta SQL generada internamente.

 

AdCmdStoredProc       Indica que es un nombre de procedimiento almacenado

 

AdCmdUnknown          Predeterminado. El tipo de comando de la propiedad CommandText                                es desconocido.

 

 

Propiedad ConnectionString

 

Esta propiedad ya le hemos visto más atrás. Es la cadena de conexión con la base de datos.

 

 

Propiedad CursorLocation

 

Es la misma que la vista para el objeto Recordset.

 

Propiedad CursorType

 

Es la misma que para el objeto Recordset. Acepta los valores:

1 – adOpenKeyset

2 - adOpenDynamic

3 – adOpenStatic

 

Propiedad EOFAction

 

Establece la forma de proceder cuando llega a la fila EOF. Acepta los valores:

 

0 – adDoMoveLast         Vuelve a la última fila

1 – adStayEOF              Permanece en la fila EOF

2 – adDoAddNew           Añade una nueva fila

 

 

Propiedad LockType

 

Tipo de Bloque. Igual a la misma propiedad del Objeto Recordset

 

Propiedad MaxRecords

 

Es similar a la del Objeto Recordset. Establece el número de filas que obtiene en su recordset asociado.

 

Propiedad Mode.

 

Igual a la misma propiedad del objeto Recordset

 

Propiedades Password

 

Establece la contraseña para crear la cadena de conexión durante la creación del objeto Recordset asociado. Esta contraseña es la contraseña del usuario en la base de datos.

 

Esta propiedad es solamente de escritura. Si se pretende leer da error.

 

Propiedad UserName

 

Establece el nombre del usuario. Debe ser uno de los usuarios registrados en la base de datos. Esta propiedad es de lectura y escritura. El valor de la propiedad Password debe ser el asociado a este usuario.

 

Propiedad RecordSource

 

Es una cadena de caracteres con el nombre de una tabla o una sentencia SQL que devuelve filas.

 

Métodos del control Adodc

 

UpdateControls

 

Actualiza la información de los controles enlazados a datos.  No existe el método UpdateRecords.

 

Refresh

 

Vuelve a construir el recordset. Es idéntico al del control Data de DAO.

 

 

Vistas ya las propiedades y métodos del control Adodc, vamos a ver un poco como funciona y cuales son sus diferencias con el control data de DAO

 

Funcionamiento del Adodc

 

El Adodc puede enlazar una base de datos a los típicos controles enlazados (Label, TextBox) usando la tecnología ADO. Los demás controles enlazados no tienen un comportamiento igual con el Adodc, Control Data o RDODataControl. En la siguiente lista puede ver que controles trabajan con uno u otro control Data.

 

 

Control              ADO     RDO     DAO     Referencia

 

DBGrid              NO       SI         SI         Microsoft Data Bound Grid Control 5.0 SP3

DataGrid           SI         NO       NO       Microsoft DataGrid Control 6.0 (OLEDB)

DataList            SI         SI         SI         Microsoft Data List Controls 6.0 (OLEDB)

DataCombo       SI         SI         SI         Microsoft Data List Controls 6.0 (OLEDB)

DBList              SI         SI         SI         Microsoft Data Bound List Controls 6.0

DBCombo         SI         SI         SI         Microsoft Data Bound List Controls 6.0

MSFlexGrid       NO       SI         SI         Microsoft FlexGrid Control 6.0

MSHFlexGrid     SI         NO       NO       Microsoft Hierarchical FlexGrid Control 6.0 (OLEDB)

 

Por lo demás el funcionamiento del Adodc es similar al Control data y al RDODataControl.

 

Con este capítulo creo que ya tienen conocimientos suficientes para empezar a trabajar con ADO, y por la tanto, ya tiene permiso para aprender a programar con esta tecnología.  Le recomiendo paciencia, y sobre todo no tener miedo a esta tecnología. Y como se dijo al principio, úsela siempre que tenga que usar una base de datos instalada en un servidor y conectada al usuario a través de una red de área local. En el próximo capítulo verá como se enlazan un cliente con el servidor SQL Server.

 

De cualquier forma no olvide la tecnología DAO para sus pequeñas aplicaciones, con la base de datos en el mismo ordenador que la aplicación. Personalmente creo que es mucho más rápida y más sencilla.

Suerte.

 

 

Home | VB |