Visual Basic Basic - Guía del Estudiante Cap. 14 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 rebusc rebuscad adas, as, que que más más que que facili facilitar tar el estud estudio, io, atemo atemoriz rizan an al princi principi pian ante. te. La Guía Guía del 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 permite crear crear aplica aplicacio cione nes s capace capaces s de manipu manipular lar base bases s de datos datos a través través de un proveedor OLE DB (Object Linking and Embedding for DataBase). El objetivo de OLE DB es poner poner a disposició disposición n del programado programadorr una herramienta 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ó electrónic nico, o, una una hoja hoja de cálcul cálculo o u otro otro tipo de almace almacenam namien iento to de datos datos.. Debid Debido o a la complejidad de los elementos de OLE DB, no se puede acceder a ellos directamente desde Visu Visual al Basic; Basic; para para ello ello utiliza utilizarem remos os los los objeto objetos s ADO que que permite permiten n acced acceder er a la práctic práctica a totalidad de las funciones de OLE DB.
O L E
s o t a d s o l a e d e c c a e u q n ó i c a c i l p A
Bases de datos Relacionales
D B
A D O
O D B C
Texto
Modelo de datos ADO R D O D A O
Bases de datos relacionales
O D B C
Modelo DAO/RDO
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 1
Las características generales de ADO son: • •
Mayor velocidad y fa cilidad de uso. Menor carga de memoria y de espacio en el disco duro.
Las características específicas que proporciona ADO para entornos de Cliente/Servidor (C/S) son: Creación de los objetos de forma independiente. No se necesita navegar por ninguna jerar jerarqu quía ía de objet objetos os para para pode poderr crearl crearlos os.. La mayoría mayoría de los objeto objetos s se pued pueden en instancia instanciarr de f orma indepen independien diente. te. De esta esta forma crearemos crearemos solo los objetos que necesitemos. ADO nos permite utilizar los procedimientos almacenados en el sistema gestor de la base de datos (si este soporta esta funcionalidad), pudiendo recoger los resultados devueltos por dichos procedimientos como parámetros de salida. Esta característica permite mejorar el rendimiento y la rapidez de las aplicaciones. Diferentes tipos de cursores. Soporte para limitar el número máximo de registros devueltos de una sola vez en un recordset. Esta característica mejora el rendimiento tanto de la aplicación como de la red. Soporte para recibir varios recordset como resultados devueltos de un procedimiento almacenado. •
•
• •
•
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 ref ieren a dichos tipos de procedimientos. Fig 72.1 Jerarquía de Objetos ADO. Connection* Error*
Er rors Command *
Parameter *
Parameters
Recordset *
Field*
Fields
* Todos los objetos marcados con un asterisco contienen la colección Properties con un subconjunto de objetos Property. Properties Pro ert
Como puede verse en la figura, existen tres objetos principales dentro de ADO: El objeto Conn Connect ection ion,, el objet objeto o Comman Command d y el objet objeto o recor recordse dset. t. Lueg Luego o veremos veremos algun algunas as 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 ADO en vez ve z 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
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 2
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 pues puesto tos s de operaci operación ón.. En esta esta base base de datos, datos, el método método ideal ideal de acceso acceso es DAO, bien 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 accediendo a través tra vés de la dirección IP del serv idor. 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 datos tipo Oracle o SQLServer. Ya empezamos a tener problemas: Visual Visual Basic no puede acceder directamente a abrir estas bases de datos. Podemos acceder a través de ODBC, ODBC, pero pero como como ya se dijo dijo en el, capítu capítulo lo corres correspo pondi ndient ente, e, ODBC ODBC se ha quedad quedado o 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 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. ODBC. Con Con ODBC ODBC se prep prepara aran n conexi conexion ones es perma permane nente ntes s en el orden ordenad ador or,, y cualq cualquie uier r 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 datos a través través de ADO, cada progra programa ma prepara prepara una conexió conexión n a esa esa BD. En ODBC podríamos ver las conexiones existentes en el PC a través del Panel de Control | Fuentes de Datos ODBC. ODBC. En ADO no existe existe esa posibilid posibilidad ad ya que, como se ha dicho, 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 aquello del juego de niños). En ADO podemos crear cada objeto objeto sin que exista el objeto inmediatamente inmediatamente superior. superior. Por ejemplo podemos 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 funcion funcionalid alidad ad del del provee proveedo dorr de los los dato datos s podre podremo mos s utiliza utilizarr deter determin minad adas as propie propieda dade des, s, métodos y colecciones de este objeto. objeto. La función de este objeto es recoger recoger toda la info rmación del proveedor de los datos que se va a utilizar para crear un objeto recordset. Para crear un objeto Connecti Connection, on, previamente previamente debemos debemos declararlo declararlo como variable objeto Connection: Dim MiConexion as ADODB.Connection ADODB.Connection El sitio donde se debe declarar depende como siempre, del ámbito que deseamos que tenga ese objeto. Para crear el objeto Connection Connection deberemos utilizar la l a siguiente sintaxis:
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 3
Set MiConexion = New ADODB.Connection 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á ¿está creada?. Sí, pero de momento es completamente completamente inútil ya que no sabe sabe ni siquiera que base de datos debe abrir, ni con que usuario, ni las condiciones en las que debe abrir esa base base (Solo lectura, etc.) Esta información información se la pasamos pasamos mediante mediante la propiedad propiedad ConnectionString 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
Espe Especific cifica a el nombre nombre del provee proveedo dorr que que se usa usa en la conexió conexión. n. (Oracle (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 Espe Especific cifica a la clave clave utiliza utilizada da por por el usua usuario rio para para abrir abrir la conexi conexión ón.. Debe Debe coincidir con el que tiene ese usuario registrado en la Base de datos. File Name Especifica Especifica el nombre nombre del fichero específico específico de proveedor proveedor,, que contiene contiene la inform informac ació ión n de confi configu gura raci ción ón de la cone conexi xión ón.. Este Este fiche fichero ro es útil ú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, Oracle, con el usuario que esa BD tiene por defecto (scott) y el Password Password de este usuario 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;’
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 4
Para una base de datos SQLServer "Provider=SQLOLEDB.1;Password=ayudas01; User ID=ayudas01; Initial Catalog=Ayudas_M; Catalog=Ayudas_M; Data Source=ayudas_sql" (en una línea única) Como puede comprobar comprobar,, resulta resulta una tanto complicado complicado construir construir la cadena cadena de conexión 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 probaremos si la l a conexión es satisfactoria o no. Truco para construir la cadena de conexión. Primero tenemos que incluir el componente “Microsoft ADO data control 6.0 (OLEDB)”. Podemos hacerlo hacerlo pulsando Ctrl.-T o en el menú Proyecto Componentes. 2) Metemos Metemos en nuestr nuestro o formulario el control control y pulsamos pulsamos F4 para para ver sus propied propiedade ades. s. 3) Hacem Hacemos os Click Click en en la la pro propie pieda dad d ConnectionString ConnectionString y nos aparecerá el botón de puntos suspensivos. suspensivos. Hacemos Click en el botón.
1)
4) Ahor Ahora a nos apar aparec ece e el asis asiste tent nte e que nos mostrará mostrará 3 opcione opciones. s. Util Utiliz izar ar un DSN DSN de arch archiv ivo, o, 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. Usarem remos la cadena de conexión (opción por defecto) y pulsaremos el botón generar.
5) Al puls pulsar ar el botó botón n gene generar rar,, nos nos apar aparec ece e otra otra venta ventana na en la que que tene tenemo mos s cuatr cuatro o pestañas aunque únicamente necesitaremos dos de ellas para crear una cadena de
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 5
conexión correcta y probada. El resto de las pestañas forman parte de otro capítulo exclus exclusivo ivo del del contr control ol data data de ADO, aunq aunque ue le invito invito a que que curio curiose see e por por ellas 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 Pestaña conexión, conexión, tenemos tenemos que proporciona proporcionarr los datos datos correspo correspondie ndientes ntes al proveedor de la base de datos a la que queremos conectar. 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, 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 S QL*Plus). En esta pestaña existen dos opciones interesantes: “Con “Contra trase seña ña en Blan Blanco co”, ”, si la marc marcam amos os no nos nos permi permitir tirá á tecle teclear ar 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. •
•
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 6
Prueba de conexión (fallida) con Proveedor de datos de Oracle
Prueba satisfactoria 7) Una Una vez que que hemos hemos probad probado o satisf satisfact actoriam oriamen ente te la conex conexión ión,, pulsa pulsarem remos os aceptar 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 olvi olvide de de que es una cade cadena na y que cuan cuando do se asig asign ne a la prop propie ieda dad d ConnectionString ConnectionString debe ir entre comillas dobles. 8) Una vez que hemos hemos proba probado do que que funciona funciona al abrir el objeto objeto Connecti Connection, on, No debemo debemos s 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. Password. Solamente queda queda aplicar un método del del objeto Connection: Connection: el método Open con una sintaxis que no es excesivamente difícil: Miconexión.Open
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 7
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) (Server_SQL_Mae) y no por su dirección IP. IP. Obviamente el nombre nombre del servidor corres correspon ponde derá rá a una una direcc direcció ión n IP (Vamos (Vamos a consi consider derar ar una una red IP estática estática,, pues pues si pre prete tend ndem emos os entr entrar ar a expl explic icar ar lo que que es una una red red con con dire direcc ccio ione nes s IP asig asigna nada das s dinámicamente se nos complica la explicación). Esa dirección IP debemos indicársela al PC en el fiche fichero ro Hosts Hosts (o Lmho Lmhosts) sts) que están están en la carpeta carpeta Window Windows s 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 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 demostra demostrarr como funciona 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 ADODB.Connection 'MiConexion.ConnectionString 'MiConexion.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\GuiaDelEstudiante\ADO\PruebaADO.mdb;Pe Source=C:\GuiaDelEstud iante\ADO\PruebaADO.mdb;Persist rsist 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 pueda existir un objeto Recordset Recordset primero hay que declararlo: declararlo: Dim MiRecordset As ADODB.Recordset ADODB.Recordset
(Hay que declararlo en el sitio adecuado adecuado dependiendo del ámbito que necesite)
En el procedimiento donde se vaya a crear el recordset, para crearlo utilizaremos la siguiente sintaxis: Set Set MiReco MiRecord rdse sett = New New ADODB.R ADODB.Reco ecords rdset et
(Ya (Ya está está cread creado. o. Pero Pero no está está abie abierto rto,, ahor ahora a hay que abrirlo)
MiRecordset.Open 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. optimista. Podríamos elegir ciertos registros, y solamente unos campos. campos. Utilizaríamos Util izaríamos una sentencia SQL MiRecordset.Open MiRecordset.Open "Select Alumno_Nombre, Alumno_Ape1, Alumno_Ape1, Alumno_Ape2 From Alumnos " _ & “Where Alumno_Nombre = ‘Luis’”, MiConexion, adOpenDynamic, adOpenDynamic, adLockOptimistic adLockOptimistic Si no hubié hubiése semos mos cread creado o previam previament ente e el objet objeto o Conn Connecti ection, on, podrí podríamo amos s crear crear y abrir abrir igua igualme lment nte e este este obje objeto to reco record rdse set, t, pero pero,, en vez de pasa pasarle rle el nomb nombre re de la cone conexió xión n (MiConexion) le pasaríamos la cadena de conexión usada para crear ese objeto Connection.
Set MiRecordset = New ADODB.Recordset ADODB.Recordset MiRecordset.Open MiRecordset.Open "Alumnos", "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\GuiaDelEstudiante\ADO\PruebaADO.mdb;Pe Source=C:\GuiaDelEstud iante\ADO\PruebaADO.mdb;Persist rsist Security Info=False", adOpenDynamic, adOpenDynamic, adLockOptimist adLockOptimistic ic
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 8
(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 W orkspace, el objeto DataBase y el objeto Recordset Set MiSesion = W orkspaces(0) orkspaces(0) Set MiBase = MiSesion.OpenDatabas MiSesion.OpenDatabase e (“C:\GuiadelEstudian (“C: \GuiadelEstudiante\Alumnos.Mdb”) te\Alumnos.Mdb”) Set MiRecordset MiRecordset = MiBase.OpenRecordset MiBase.OpenRecordset (“Alumnos, dbOpenDynaset) dbOpenDynaset) Con ADO (Creando el objeto Connection) Declarar MiConexion y MiRecordse Mi Recordsett Dim MiConexion As ADODB.Connection ADODB.Connection Dim MiRecordset As ADODB.Recordset ADODB.Recordset Crear la conexión y ponerle la cadena de conexión en su propiedad ConnectionString ConnectionString Set MiConexion = New ADODB.Connection ADODB.Connection MiConexion.ConnectionString MiConexion.ConnectionString = "P rovider=Microsoft.Jet. rovider=Microsoft.Jet.OLEDB.4.0;Data OLEDB.4.0;Data Source=C:\GuiaDelEstudiante\ADO\PruebaADO.mdb;Pe Source=C:\GuiaDelEstud iante\ADO\PruebaADO.mdb;Persist rsist Security Info=False" Abrir el objeto Connection MiConexion.Open Crear el objeto recordset Set MiRecordset = New ADODB.Recordset ADODB.Recordset Abrir el objeto Recordset Recordset MiRecordset.Open MiRecordset.Open "Alumnos", MiConexion, adOpenDynamic, adLockOptimistic Con ADO (Sin crear el objeto Connection) Declarar MiRecordset MiRecordset Dim MiRecordset As ADODB.Recordset ADODB.Recordset Crear el Recordset Set MiRecordset = New ADODB.Recordset ADODB.Recordset Abrir el Recordset Recordset MiRecordset.Open MiRecordset.Open "Alumnos", "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\GuiaDelEstudiante\ADO\PruebaADO.mdb;Pe Source=C:\GuiaDelEstud iante\ADO\PruebaADO.mdb;Persist rsist Security Info=False", adOpenDynamic, adOpenDynamic, adLockOptimist adLockOptimistic ic 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
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 9
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 e jecutándose jecutándose en el servidor, serv idor, 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 MiSe MiSesi sion on.C .Clo lose se
(Rec (Recue uerd rde e qu que deb debe e cer cerra rarr ant antes es el reco record rdse sett que que la cone conexi xión ó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 DataBase WorkSpace
Recordset Connection ¿
Efectivamente Efecti vamente el Workspace Workspace no tiene algo que pudiésemos 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 emple empleo o de base bases s de dato datos s complej complejas as en cuanto cuanto a segu segurid ridad ad nos nos va a obse obsequ quiar iar con limitaciones a los recordsets que que vamos a abrir en ADO. Y además esas esas sorpresas 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 modestia que le caracteriza, no va a dar ningún ningún problema.) problema.) Los recordsets abiertos mediante una consulta SQL (aquellos en los que seleccionamos parte de los los regi regist stro ros s medi median ante te Select … Where van van a crea rearse rse solo solo de lect lectur ura. a. 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. lectur a. También observará 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. 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 acepte escritura y movimiento hacia atrás. Eso generalmente generalmente se logra abriendo el recordset recordset con todos los registros de la tabla, e incluyendo en él todos los campos. En vez de : MiRecordset.Open MiRecordset.Open "Select Alumno_Nombre, Alumno_Ape1, Alumno_Ape1, Alumno_Ape2 From Alumnos " _ & “Where Alumno_Nombre = ‘Luis’”, MiConexion, adOpenDynamic, adOpenDynamic, adLockOptimistic adLockOptimistic usar esta otra alternativa: MiRecordset.Open 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 queramos introducir un nuevo registro mediante:
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 10
MiRecordset.A t.AddNew nos dirá dirá qu que el cu cursor (el (el rec recordset, par para ent entendernos) es solamente de lectura. La solución es, abrir el recordset con la sintaxis anterior, leer el número de Alunmo_ Alunmo_ID, ID, cerrar el recordse recordset, t, crear otro recordset recordset con el mismo nombre, nombre, usando usando la sintaxis: MiRecordset.Open MiRecordset.Open "Alumnos", MiConexion, adOpenDynamic, adLockOptimistic Ahora Ahora ya nos permitirá permitirá usar el método AddN AddNew ew.. Basta Basta con añadir las líneas líneas de código adecuado adecuado para introducir los valores valor es 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 introducir los datos “a capón” utilizando la instrucción SQL Insert que ya veremos más adelante. SQLServer SQLServ er 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 sin come comenza nzarr por por la línea línea Mirec Mirecor ords dset. et.Ed Edit. it. Colo Colocá cánd ndon onos os en el regi registr stro o a modifi modifica car r 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. adelante. Hasta ahora 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 esta es una una técn técnica ica comp comple letam tamen ente te acce accesi sibl ble, e, aunq aunque ue,, dada dadas s las las gran grande des s prestaciones prestaciones que tiene, un poco más adelante se va a complicar algo. Ya ha visto v isto 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 que adornar 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 capón” un nuevo registro, o borrarlo, utilizando directamente directamente instrucciones SQL. Hay que que darse darse cuenta cuenta que ADO trabaja con una gran diversidad de bases de datos, y no todas trabajan igual. Por eso, eso, muchas muchas veces fallan operacione operaciones s tan sencilla sencilla como añadir un nuevo registro registro con el método AddNew del recordset MiRecordset.AddNew Y hay que emplear una instrucción SQL: INSERT
LSB
Visual Basic Guía del Estudiante
Capítulo Capítu lo 14
Página 11
En estos casos, casos, en ADO utilizamos el método EXECUTE sobre el objeto Connection. Connection. Creamos una una variable variable,, StrIntro StrIntrodu ducir cir,, con con el conten contenid ido o de la instruc instrucció ción n SQL y ejecut ejecutába ábamos mos esa esa instrucción mediante Execute StrIntroducir = "Insert Into INT_DOCUMENTOS " _ & "(CL_DOC,NOM_DOC,TITULO_DOC,AUTOR_DOC "(CL_DOC,NOM_DOC,TITULO_DOC,AUTOR_DOC,CL_TEMA_DOC,CL_ ,CL_TEMA_DOC,CL_DPT_DOC,” DPT_DOC,” _ & “L_TIPO_DOC,FICH_DOC,FECHA_EMISION_DOC,UL “L_TIPO_DOC,FICH_DOC,FECHA_E MISION_DOC,ULTIMA_HORA_DOC,VISIBLE_DOC)"_ TIMA_HORA_DOC,VISIBLE_DOC)"_ & "Values "Values (" & NumeroDocumento NumeroDocumento & ",'" & TbTitulo & "','" & TbTitulo & "','" & TbTitulo.Tag TbTitulo.Tag _ & "',19,2,1,'" & HRefPrensa & "/" & TbNombFichTIF & "','" & Date & "',0,1)" ConexBDPrensa.Execute ConexBDPrensa.Execute StrIntroducir Esta Esta línea línea (StrInt (StrIntrod roducir ucir)) es el conten contenido ido de la propi propieda edad d Comman CommandT dText ext de un objet objeto o 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 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, expresiones, pero dándole dándole más cuerpo. Con la instrucción anterior, 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 Recordset StrIntroducir = “Select * From Alumnos Where Apellido1 = ‘Suarez’” Podem Podemos os crear crear un record recordse sett (MiReco (MiRecords rdset, et, previam previament ente e decla declara rado do como como tal) tal) con con esta esta instrucción Execute StrIntroducir MiRecordset = ConexBDPrensa. ConexBDPrensa.Execute O con estas otras Set MiComando as New ADODB.Command MiComando.ActiveConnection = ConexBDPrensa ConexBDPrensa MiComando.CommandText MiComando.CommandT ext = “Select * From Fr om 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 un Command, vamos a entrar a conocer sus sus propiedades propiedades y métodos. Al final, y con un buen ejemplo realizado de varias formas, entenderá perfectamente la forma de trabajar con ADO.
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 12
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 Como pued puede e verse verse en la figura, figura, el Objeto Objeto Conn Connecti ection on tienen tienen los objetos objetos Comman Command d y Recordset, 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 acces acceso o a datos datos y usarl usarlas as en el momen momento to adecu adecuad ado, o, simplem simplement ente e citánd citándola olas. s. Lo que 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 tratados de la forma habitual: mediante Err Propied Propiedade ades s del Objeto Objeto Connec Connection tion (Lea (Lea esto esto de las las propi propied edad ades es sin compli complicar carse se 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 Esto Estos s atrib atribut utos os cond condic icio iona nan n el modo modo de oper operaci ación ón de la cone conexió xión n con con los los métod métodos os CommitTrans y RollBackTrans. RollBackTrans. Propiedad CommandTimeout Indica Indica,, en segu segund ndos os,, el interval intervalo o de espe espera ra para para que que se ejecut ejecute e un comand comando o (Objet (Objeto o Comman Command) d) antes antes de que que finalice finalice el inten intento to y se genere genere un error error.. Es un Long Long.. El valor valor predeterminado es 30. Propiedad ConnectionTimeout Indica, en segundos, segundos, el intervalo i ntervalo de espera 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.
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 13
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 va rios argumentos, todos ellos separados separados por un punto y coma (;) de la forma argumento1 argumento1 = valor; valor; argumento2 argumento2 = valor; argumento argumento3 3 = valor etc. ADO procesa solamente cuatro argumentos: Provider, File Name, Remote Provider y Remote Server. Server. Los demás demás argumento argumentos s los pasa al proveedor proveedor para que el los procese procese (Usuario, (Usuario, Password, etc) Si al emplear emplear el método método Open Open se utiliza el parámetro parámetro Connection Connection String, este parámetro parámetro utilizado utilizado en el método método Open Open sustituirá sustituirá a cualquier cualquier otro existente existente anteriormen anteriormente. te. 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 Provider son excluyentes. Propiedad CursorLocation
(IMPORTANTE)
Estab Establec lece e o devuelve devuelve la posici posición ón de un servicio servicio de cursor cursores es.. Es un Long Long,, y acepta acepta las siguientes constantes: AdUseNone
No se usan servicios de cursor. (Esta constante es obsoleta y aparece únicamente por compatibilidad con vers iones anteriores.) 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 t ienen 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 que los los haya haya cons conseg egui uido do viene viene su prim primer era a duda duda:: ¿Dón ¿Dónde de los los almac almacen eno? o? Pued Puede e 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 almacenar los datos obtenidos 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 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 prop propie ieda dad d muy usad usada, a, Abso Absolut luteP ePos ositi ition on,, no la tiene tienen n los los curs cursor ores es de lado lado servi servido dorr, 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 MiConexion.CursorLocation = adUseClient adUseClient
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 14
Si desea hacer transacciones, deberá crear cursores del lado servidor, ya que los de lado cliente cliente no las admite admiten. n. Compre Comprend nderá erá segú según n vaya progr programa amando ndo y encon encontrá tránd ndos ose e 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 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. BeguinTrans. Vea la ayuda para mayor información de los valores posibles. 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 propiedad Mode cuando el objeto Connection está cerrado. Cuando se usa en un objeto Connection del lado del cliente, cliente, la propied propiedad ad Mode sólo se puede establecer establecer a adModeUnknown. adModeUnknown . Propiedad Provider Es un string que indica el nombre del proveedor de un objeto Connection. Si no se especifica ningún ningún proveedor proveedor,, la propieda propiedad d tendrá tendrá el valor predetermin predeterminado ado MSDASQL MSDASQL (Proveedor (Proveedor de Microsoft OLE DB para ODBC).
Propiedad State Devuelve el estado del objeto Connection: abierto (adStateOpen = 1) o cerrado (adStateClosed (adStateClosed = 0).
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 15
Propiedad Version Devuelve el número de versión de ADO. Es un String.
Métodos del Objeto Connection Métodos BeginTrans, CommitTrans y Rollback Trans Estos métodos de transacción administran el proceso de la transacción dentro de un objeto Connection de la forma siguiente: BeginTrans: BeginTrans: inicia una nueva t ransacción. ransacción. •
•
•
CommitTrans: CommitTrans: guarda las modifi caciones y termina l a transacción actual. También También puede iniciar una nueva transacción. RollbackTrans: RollbackTrans: cancela las modif icaciones efectuadas durante durante la transacción actual y termina la transacción. También También puede iniciar una nueva transacción.
Después de invocar el método BeginTrans, BeginTrans, el proveedor ya no aplicará inmediatamente las modifica modificacio cione nes s hasta hasta que que invoque invoque CommitTrans o RollbackTrans para para termi termina narr la BeginTrans, CommitTrans y RollbackTrans no están disponibles transacción. Los métodos BeginTrans, en los objetos Connection del lado del cliente.
Método Cancel Open. Cancela la ejecución de una llamada asíncrona pendiente a un método Execute u Open. NombreConection.Cancel
Sintaxis
El método Cancel se utiliza para terminar la ejecución de una llamada asíncrona a un método Execute o Open (es (es decir decir,, el méto método do fue fue invoc invocad ado o con con la opció opción n adAsyncConnect, adAsyncConnect, adAsyncExecute o adAsyncFetch). 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. 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. Recordset. El cierre explícito de Close) mientr un objeto objeto Connection (llamando a su método Close) mientras as una una trans transacc acció ión n está está en progre progreso so gene genera ra un error error.. Si un objet objeto o Connection cae cae fuera fuera del del alcan alcance ce mientra mientras s 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 var iable de objeto a Nothing . Set NombredelObjetoConnection = Nothing Método Execute (Vea también Método Execute para el objeto Command) Ejecuta Ejecuta una consulta, consulta, instrucción instrucción SQL, procedimie procedimiento nto almacenad almacenado o especificad especificados os o texto específico del pro veedor. veedor. Sintaxis (Para una cadena cadena de comando que no devuelva devuelva filas):
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 16
conexión.Execute conexión .Execute CommandText , RecordsAffected , Options (Para una cadena de comando que devuelva filas): Set MiRecordset = connection.Execute connection .Execute (CommandText , RecordsAffected , Options) Options) (MiRecordset debe ser una variable declarada tipo ADODB.Recordset) ADODB.Recordset) CommandText Es u n String String que que conti contien ene e la instru instrucció cción n SQL, SQL, el nombre nombre de la tabla, 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 adCmdText adCmdTable adCmdTableDirect adCmdTable adCmdStoredProc adCmdUnknown adAsyncExecute adAsyncFetch
Descripción Indica que el proveedor tiene que e valuar CommandText valuar CommandText como como definición textual de un comando, como una instrucción SQL. Indica que ADO tiene que generar una consulta SQL para devolver todas las filas de la tabla mencionada en CommandText . Indica que el proveedor tiene que devolver todas las f ilas de la tabla mencionada en CommandText . Indica que ADO tiene que generar una consulta SQL para devolver todas las filas de la tabla mencionada en CommandText . Indica que el proveedor tiene que e valuar CommandText valuar CommandText como como procedimiento almacenado. Indica que el tipo de comando en CommandText es CommandText es desconocido. Indica que el comando se tiene que ejecutar de fo rma asíncrona. Indica que el resto de las filas siguientes a la cantidad inicial especificada en la propiedad propiedad CacheSize tiene que ser recuperada de forma asíncrona. asíncrona.
Cuando esta operación operación termina se genera el evento ExecuteComplete. Método Open
(IMPORTANTE)
Abre una conexión a un origen de datos. Sintaxis
MiConnection.Open onnection .Open ConnectionSTring , UserID, UserID, Password, Password, Options MiConnection MiConnection.Open .Open
Los parámetros ConnectionSTring , UserID, UserID, Password, Options puede introducirlos previamente a abrir abrir la conexi conexión, ón, y utiliza utilizarr la segu segund nda a sintaxi sintaxis s cuan cuando do dese desee e abrirl abrirla a realme realmente nte.. Estos Estos parámetros se le pasan en la cadena de conexión: ConexBDPrensa.Connection ConexBDPrensa.ConnectionString String = "Provider=MSDAORA.1;User ID=INTRANET;” & _ “Password=INTRANET “Password=INTRANET;Data ;Data Source=intranet;Persist Source=intranet;Persist Security Info=False" Options Opcional. Puede ser una de las constantes siguientes: AdConne AdConnectUns ctUnspecified pecified Abre la conexión conexión de forma sincronía sincronía AdAsy AsyncC ncConnect Abre la conexió exión n de form forma a asín síncro crona Cuando Cuando se usa un objeto Connection Connection del lado del cliente, cliente, el método Open no establece establece realmente una conexión con el serv idor 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 Error representa un error específico del proveedor, no un error ADO. Los errores ADO ADO se exponen al mecanismo de control de excepciones en tiempo de ejecución.
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 17
Por ejemplo, en Microsoft Visual Basic, cuando ocurre un error específico de ADO dispara un evento On Error y 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. Errors . Las operaciones ADO que no generan un error no tienen ningún efecto sobre la colección Errors. 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: Description: Contiene la descripción del error producido (String). NativeError: Indica el error devuelto por la base de datos (Long). (Long). Number: Es el código de error (Long). Source: Indica el nombre del objeto o aplicación que ha generado el error (String). SQLState: Indica el error SQL estándar asociado.(String). asociado.(String). Debido a que este objeto será de gran utilidad a continuación se incluye un ejemplo de su uso. Ejemplo del tratamiento de errores: El resultado de la ejecución es el siguiente: • • • • •
Private Sub CBConexion_Click() Dim MiConex1 As ADODB.Connection ADODB.Connection Dim MiError MiE rror As ADODB.Error On Error GoTo RutErr Set MiConex1 = New ADODB.Connection ADODB.Connection MiConex1.ConnectionString MiConex1.ConnectionString = "Provider=MSDAORA.1;Passwor "Provider=MSDAORA.1;Password=tiger;User d=tiger;User ID=EScot ID=EScot;Data ;Data Source=MADRID;Persist Security Info =True" =True" MiConex1.Open Exit Sub RutErr: For Each MiError In MiConex1.Errors M iConex1.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
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. description. Con este comentario comentario se pretend pretende e sugerir sugerir que se realicen realicen pruebas pruebas con el proveedor proveedor de datos 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
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 18
Es el conjunto de objetos Property Objeto Property Un objeto Property representa 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. dinámicas. Las Las prop propie ieda dade des s intrí intríns nsec ecas as son son aque aquella llas s prop propie ieda dade des s implem implemen enta tada das s en ADO ADO e inme inmedi diat atam amen ente te disp dispo onibl nibles es para ara cual cualqu quie ierr nuev nuevo o obje objeto to,, util utiliz izan and do la sint sintax axis is Objeto. Objeto.Propiedad. Propiedad . No aparecen como objetos Property en la colección Properties de un obje objeto to,, de forma forma que que aunq aunque ue pued puede e modifi modifica carr sus sus valor valores es,, no pued puede e modifi modifica carr sus 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. 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 Objeto.Properties("Name"). ("Name"). Un objeto Property dinámico tiene ti ene cuatro propiedades incorporadas 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 pro veedor. veedor. • • • •
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 Especifica la posición posición ordinal del registro registro actual de un objeto objeto Recordse Recordset. t. Esta propiedad propiedad devuelve un Long con el número de orden del registro. Es posible que el recordset no acepte esta propiedad, propiedad, dependiendo dependiendo del proveedor proveedor de datos, y del tipo de cursor (lado cliente o lado servidor. El cursor tipo lado servidor no permite esta propiedad) propiedad) Esta propiedad propiedad devolverá 1 cuando el registro actual sea el primer registro del recordset.
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 19
Propiedades BOF y EOF Indican Indican si la posición posición del puntero puntero del Recordse Recordsett está apuntand apuntando o a un registro anterior anterior al primero (BOF = True) o posterior al último (EOF = True). Esta propiedad siempre la podremos mirar, independientemente independientemente si el cursor es lado cliente o lado servidor. Propiedad ActiveConnection (ADO) Indica Indica a qué objeto Connectio Connection n pertenec pertenece e actualmen actualmente te el objeto objeto Recordse Recordsett especificad especificado. o. 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 E l valor del Bookmark hay que introducirlo en una variable tipo Variant. La propiedad propiedad Bookmark Bookmark solo podrá establecer establecerse se cuando cuando el proveedor proveedor lo permita. permita. Puede Puede utilizarse el método Supports para para averiguarlo. averiguarlo. Cuando Cuando el records recordset et es de lado lado cliente, siempre está disponible el Bookmark. Propiedad CacheSize Indica el número de registros del objeto Recordset que están están en la memoria me moria caché local. Es un Long de lectura y escritura. El va lor 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, Recordset, el proveedor recupera los 10 primeros registros en la memoria local. A medida que se desplaza por el objeto Recordset, Recordset, el proveedor devuelve los datos desde el búfer de memoria local. Tan Tan pronto como pasa del último registro de la memoria caché, el proveedor recupera los 10 registros siguientes 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 Resync . la memoria caché, debe usarse 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 predete predetermin rminad ado o es 0, que que signific significa a sin límite (Obtien (Obtienen en todos todos los los regist registro ros). s). Esta Esta propie propieda dad d es de lectur lectura a y escrit escritura ura cuand cuando o el record recordse sett está está cerrad cerrado, o, 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 culpa a Windows Si estamos frente a una base base de datos 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 Afi liados 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 puesto de operación operación público (Acceso desde Internet Internet por ejemplo). Con la propiedad MaxRecords puede limitar el número de registros obtenidos. obtenidos. Posiblemente no llegue a obtener el dato deseado, deseado, y se vea ve a en la obligación de realizar la misma consulta sucesivas veces hasta encontrarlo.
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 20
Propiedad CursorLocation Establece o devuelve la posición de un servicio servicio de cursores. Es idéntica a la propiedad propiedad del mismo nombre vis ta más atrás con todo detalle para el objeto Connection. Propiedad CursorType CursorType Indica el tipo t ipo 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 usuarios eliminan son inaccesible inaccesibles s desde desde su conjunto de registros registros.. Los 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 entre registros, registros, a excepción de los marcado marcadores res si el proveedor 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 hacen otros usuarios usuarios no son 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 Recordset se abra. Para comprobar la funcionalidad específica del cursor devuelto, use el método Supports. Cuando cierre el Recordset , la propiedad CursorType propiedad CursorType volverá a su configuración original.
Propiedad Lock Type Type Indica el t ipo 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 AdLockPessimistic
AdLockOptimistic
LSB
Predeterminado. Sólo lectura—no puede modificar los datos 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. modificación. Este valor solamen solamente te es válido si el cursor cursor (Propiedad (Propiedad CursorLocation) esta establecido a lado servidor. Bloqueo optimista, registro a registro: el proveedor usa bloqueo optimista, bloqueando registros sólo cuando llama al método Update.
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 21
AdLockBatchOptimistic de
Actualizaciones optimistas por lotes: requerido para el modo actualización por lotes como contraposición contraposición al modo de actualización inmediata.
Propiedad EditMode Indica el estado de modificación del registro actual. Es solamente de lectura. Devuel ve uno de las siguientes constantes: AdEditNone AdEditInProgress AdEditAdd
AdEditDelete
Indica que no hay ninguna operación operación de modif icación en ejecución. Indica que los datos del registro actual se han modif icado pero que no se han guardado. Indica que se ha invocado el método AddNew 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. 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 especialmente lenta. Mediante Filte r puede descartar 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 propiedad Filter se utiliza también también para actuar actuar sobre sobre determinad determinados os registros registros en varios método métodos s del records recordset et (Resyn (Resync, c, Save, Save, …) pero pero no se va a explica explicarr en este manual manual la expli explica cació ción n de la utiliz utilizac ació ión n de esta esta prop propie ieda dad d en esos esos métod métodos os,, ya que que el nivel nivel del del progra programad mador or que que utiliza utiliza esos esos recurs recursos os debe debe ser ser elevado elevado.. Le reservam reservamos os por por tanto 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: ejemplo : (MiConexion es una conexión ya creada) Dim RsInicial As ADODB.Recordset ADODB.Recordset Dim RsFiltrado As ADODB.Recordset ADODB.Recordset Set RsInicial = New ADODB.Recordset Set RsFiltrado = New ADODB.Recordset RsInicial.Open "Autores", MiConexion, adOpenDynamic, adLockOptimistic ‘Este ‘Este es el record recordset set que que uso uso para para mucha muchas s cosas cosas dentr dentro o de la aplica aplicació ción. n. Ahora Ahora quiero quiero presentar en un MSHFlexGrid solamente los datos de los autores de nacionalidad española. Filtro el recordset anterior anterior utilizando utili zando un criterio de igualdad de un campo: campo: Nacionalidad RsFiltrado = RsInicial.Filter RsInicial.Fi lter (“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
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 22
Este es el único ejemplo que puedo sacar sacar de todas mis aplicaciones. Seguro que el alumno va a ver más aplicaciones de esta propiedad. propiedad. La propiedad propiedad Filter puede puede mostrar mostrar también también aquellos aquellos registros registros que han sido sido manipulad manipulados os recientemente, mediante las constantes constantes siguientes: AdFilterNone AdFilterPendingRecords
Quita el filtro actual y vuelve a poner todos los registros a la vista. Permite ver ve r sólo los registros r egistros que han cambiado, cambiado, pero que no han sido enviados aún al servidor. Aplicable sólo para el modo de actualización por lotes.
AdFilterAffectedRecords a
Permite ver sólo los registros afectados por la última llamada Delete, Resync, UpdateBatch UpdateBatch o CancelBatch
AdFilterFetchedRecords
Permite ver los registros de la caché actual, es decir, decir, los resultados resultados de la últ ima llamada lla mada para recuperar recuperar registros de la base de datos Permite ver los registros que fallaron en el último intento de actualización por lotes.
AdFilterConflictingRecords
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 utili zar un índice, el orden de los registros se cambia al orden establecido en ese ese índice. Por lo tanto, los valores obtenidos anteriormente anteriormente por la propiedad AbsolutePosition 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. cliente. En este caso, como como vimos más atrás atrás,, los regis registro tros s del del record recordse sett está están n en el equip equipo o cliente cliente.. Todas odas 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 recordse recordsett que está en el equipo equipo cliente. Mediante Mediante esta propieda propiedad d podemos podemos hacer que se envíen al servidor todos los registros (filas) o solamente los que han cambiado. Acepta estas dos constantes: AdMarshalAll AdMarshalModifiedOnly
Predeterminada. Predeterminada. Indica que todos los registros se devuelven al servidor. 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 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
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 23
registros al mismo tiempo. Esta propiedad se puede establecer en cualquier momento y su valor se utilizará util izará para calcular la ubicación del primer registro de una págin página a específica. Propiedad PageCount Indica Indica cuántas cuántas páginas páginas de datos datos contiene contiene el objeto objeto Recordse Recordset. t. Es solamen solamente te de lectura. lectura. Devuelve un Long. Si el objeto Recordset no admite esta propiedad, el valor será -1 para indicar que no se puede puede determinar el va lor de PageCount. PageCount. Propiedad AbsolutePage Especifica en qué página reside 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 AbsolutePage. proveedor no admite la propiedad propiedad AbsolutePage.
AdPosBOF
El puntero del registro actual está al comienzo del archivo (es decir, decir, la propiedad BOF tiene el valor True valor True). ).
AdPosEOF
El puntero del registro actual está al final del archivo (es decir, la propiedad EOF tiene el valor True valor True). ).
Propiedad RecordCount Indica el número actual de registros registros de un objeto 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 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 siguientes valores: Constante
Descripción Valor predeterminado. Indica que el objeto está adStateClosed cerrado. adStateOpen Indica que el objeto está abierto. Indica que el objeto Recordset se está adStateConnecting conectando. Indica que el objeto Recordset está ejecutando adStateExecuting un comando. Indica que se está obteniendo el conjunto de filas adStateFetching del objeto Recordset. 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. 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
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 24
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 deben tener un valor para poder poner poner valor a la propiedad Unique Table. 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 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 recordset acepta una determinada determinada funcionalida funcionalidad. d. Devuelve Devuelve un Boole Boolean ano o y es solam solamen ente te de lectur lectura. a. De esta forma puede puede consu consulta ltarr si un recordset admite el método Move First, la propiedad propiedad AbsolutePosition, 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 AdApproxPosition AdBookmark AdDelete AdHoldRecords AdMovePrevious
AdResync AdUpdate AdUpdateBatch AdIndex AdSeek
Puede usar el método AddNew para agregar nuevos registros. Puede leer y establecer las propiedades AbsolutePosition y AbsolutePage. Puede Puede usar la propieda propiedad d Bookmark Bookmark para tener acceso a registros registros específicos Puede usar usar el método Delete para eliminar registros. Puede recuperar más registros o cambiar la posición de recuperación siguiente sin efectuar todos los cambios pendientes. pendientes. 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. Puede usar usar el método Resync para actualizar el cursor con los datos visibles en la base de datos subyacente. Puede usar usar el método Update para modificar datos existentes. Puede usar actualización por lotes ( métodos UpdateBatch UpdateBatch y CancelBatch) para transmitir grupos de cambios al pro veedor. veedor. Puede utilizar la propiedad propiedad Index para dar nombre a un índice. Puede utilizar el método Seek para encontrar una fila en un Recordset.
En este ejemplo vemos la sintaxis de Supports: If RsSeg.Supports(adA RsSeg.Supports(adApproxPosition) pproxPosition) = True Then MsgBox "SI" Else MsgBox "NO" End If Nota Aunque Nota Aunque el método Supports puede devolver True 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
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 25
admitir admitir la funcion funcionalid alidad ad especifi especificada cada,, dando dando por supuest supuesto o que se reúnen reúnen determina determinadas das condicio condiciones. nes. Por ejemplo ejemplo,, el método método Supports puede puede indicar indicar que un objeto 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 va lor devuelto por el m étodo Supports dependerá dependerá del tipo de recordset recordset elegido. En la siguiente tabla puede ver el tipo de recordset y las constantes constantes para las que va a devolver True: AdOpenForwardOnly AdOpenKeyset AdOpenDynamic AdOpenStatic
Ninguna adBookmark, adHoldRecords, adMovePrevious, adResync adResync AdMovePrevious adBookmark, adHoldRecords, adMovePrevious, adResync adResync
Método Open Es el método que ABRE el ABRE el recordset. Este método es el que busca los registros que han de rellenar el recordset. Sintaxis. Esta es la sintaxis general: general: MiRecordset .Open .Open Source, Source, ActiveConnection, ActiveConnection, CursorType, CursorType, LockType, LockType , Options Un recordse recordsett puede puede abrirse abrirse partiend partiendo o de una conexión conexión ya abierta abierta.. Pero también también puede 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. 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 para abrir el objeto Connection. CursorType (Opcional). Un valor que determina el tipo de cursor que el proveedor debe usar al abrir el Recordset. Recordset. Puede ser una de las siguientes constantes AdOpenForwardOnly (Predeterminado) Abre Abre un cursor de tipo sólo avance. AdOpenKeyset Abre un cursor de tipo conjunto de cla ves. AdOpenDynamic Abre un cursor de tipo dinámico. (Igual que el Dynaset de DAO) AdOpenStatic Abre un cursor de tipo estático. LockType (Opcional). (Opcional) . Un valor va lor que determina el tipo de bloqueo que debe debe usar el proveedor al abrir el Recordset. 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 AdLockPessimistic
AdLockOptimistic al
LSB
(Predeterminado) Sólo lectura. No puede modificar los datos. Bloqueo pesimista, registro a registro. El proveedor hace lo necesa necesario rio para asegurar asegurar una modificación modificación correcta correcta de los registros, normalmente bloqueando bloqueando registros en el origen de datos inmediatamente antes de la modificación. Bloqu Bloqueo eo optimis optimista, ta, regist registro ro a regist registro. ro. El provee proveedo dorr usa usa bloqueooptimista, bloqueando registros sólo cuando se llama método Update.
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 26
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). (Opcional) . Constante que determina como va a evaluar el proveedor de datos el argumento Source. 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. Source. AdCmdTableDirect Indica que el proveedor debe devolver todas las fi las de la tabla nombrada en Source. 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. Source. AdAsyncExecute Indica que Source se debe ejecutar de forma asíncrona. AdAsyncFetch Indica que, tras alcanzar la cantidad inicial especificada en la Size, las f ilas restantes deben propiedad Initial Fetch Size, deben buscarse buscarse de forma asíncrona. asíncrona. Si se requiere una fila que no se ha encontrado, se bloqueará el subproceso principal hasta que se disponga 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 fi la actual se desplaza automáticamente 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 que si se cerrara el recordset y se vol viera 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, adAsyncExecute, esta operación se ejecutará de forma asíncrona y se emit irá un e vento RecordsetChangeComplete RecordsetChangeComplete cuando cuando concluya.
Método Resync Actual Actualiza iza los dato datos s del del objeto objeto Records Recordset et actual actual.. Este Este método método,, a diferen diferencia cia del del método 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 hubiera hubieran n sido creados creados con posteriorida posterioridad d a la apertura apertura del recordse recordset. t. 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 MiRecordset.Resync AffectRecords, ResyncValues
Los parámetros AffectRecords y ResyncValues determinan que registros se van a volver a leer y sobreescribir. sobreescribir. Vea la ayuda para mas detalles.
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 27
METODO AddNew Crea un nuevo registro en un objeto Recordset actualizable. Sintaxis
NombreDelRecordset ..AddNew FieldList , Values NombreDelRecordset
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 - va lor 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 NombreDelRecordset!NombredelCampo = ValorDelCampo ValorDelCampo ó NombreDelRecordset(“NombredelCamp NombreDelRecordset(“NombredelCampo”) o”) = 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 deseam deseamos os introducir introducir.. Con algún tipo de cursor es necesario 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 AddNew , ADO invoca operación AddNew, invoca autom automátic áticame amente nte el método método Update para para guardar guardar los cambios. cambios . Vea más adelante los métodos Update y UpdateBatch. 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 NombreDelRecordset .Update Fields, Fields, Values En esta sintaxis, Fi elds y Values son 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 creación de un nuevo registro mediante AddNew. Vuelvo a recomendar lo anterior. anterior. Para cambiar los v alores de varios campos de un registro, nos colocaremos sobre 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 MiRecordset.Update Pero en ADO pasa una cosa que no pasaba en DAO. Si cambiamos de registro una vez Update. Por lo modificado el valor de un registro, ADO invoca automáticamente el método Update. tanto, el código siguiente: MiRecordset!Campo1 = Valor1
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 28
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 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 CancelUpdate. método CancelUpdate.
Método UpdateBatch Escribe Escribe en disco todas todas las actualizaci actualizacione ones s pendientes pendientes de proceso 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 valor LockType se ha puesto a AdLockBatchOptimistic) Sintaxis
MiRecordset MiRecordset .UpdateBatch AffectRecords .UpdateBatch AffectRecords
AffectRecords Constante que determina a cuántos registros afectará el método UpdateBatch. UpdateBatch. Puede tomar uno de los siguientes valores. AdAffectCurrent AdAffectGroup AdAffectAll
Escribe solamente los cambios pendientes en el registro actual. Escribe los cambios pendientes que que cumplen el valor de la propiedad Filter. (Predeterminado) Escribe los cambios pendientes en Recordset. todos los registros del objeto Recordset.
Método Cancel Cancela la ejecución del método Open. Open. Sintaxis
NombreDelRecordset .Cancel NombreDelRecordset .Cancel
El método Cancel solamente puede usarse si el método Open fue invocado con la opción adAsyncConnect, adAsyncConnect, adAsyncExecute o adAsyncFetch. adAsyncFetch.
Método Delete Elimina el registro actual o un grupo de registros. registros. Por defecto eli mina solamente el registro actual. Vea la ayuda para ampliar los detalles respecto al parámetro opcional AffectRecords Sintaxis
Delete AffectRecords MiRecordset 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 MiNuevoValor Y a continuación rematar la operación mediante el método Update MiRecordset.Update
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 29
Si por cualquier cualquier circunstan circunstancia cia se ha ejecutad ejecutado o la primera instrucción, instrucción, y luego luego queremos queremos volvernos atrás, antes de ejecutar el método Update debemos deshacer el cambio con el método método Cance CancelUp lUpda date, te, con con lo que que el regis registro tro afecta afectado do recup recupera erará rá nuevam nuevament ente e su valor valor original. MiRecordset .CancelUpdate
Sintaxis
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. pendiente. Es similar a la anterior, pero para actualización por lotes. MiRecordset .CancelBatch AffectRecords CancelBatch AffectRecords
Sintaxis
Método Clone Crea un objeto Recordset duplicado a partir de un objeto Recordset existente. Opcionalmente, puede especificarse especificarse que el nuevo recordset sea solamente de lectura Sintaxis
Set rstDuplicate = rstOriginal .Clone (LockType) LockType)
(El objeto rstDuplicate debe estar declarado previamente como objeto ADODB.Recordset) ADODB.Recordset) LockType puede tomar uno de los siguientes valores: AdLockUnspecified AdLockReadOnly
(Predeterminado) El recordset resultante resultante tendrá el mismo tipo de bloqueo que el original. El recordset creado es solamente de lectura.
El record recordse sett result resultan ante te del del método método Clone, Clone, aunq aunque ue igual igual al origina originall en el momen momento to 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 .Move NumRecords, 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. especifica. Start Opcional. Un String o Variant cuyo resultado sea un marcador del tipo Bookmark. Puede utilizar también una de las siguientes constantes: constantes: AdBookmarkCurrent (Predeterminado) Cuenta a partir del registro actual AdBookmarkFirst Cuenta a partir del primer registro AdBookmarkLast Cuenta a partir del último rregistro egistro
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 30
Métodos MoveFirst, MoveLast, MoveNext y MovePrevious Pasa al primer, últim o, siguiente o anterior registro de un objeto Recordset especificado 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 MiRecordset.Find (criterio, SkipRows, searchDirection, start)
criterio Es el criterio de búsqueda. búsqueda. Por Por ejemplo “Pais = España” España” siendo Pais el nombre del campo en el cual buscamos el valor España España SkipRows (Opciopnal) Es un Long, cuyo valor predeterminado es cero, que especifica 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 final del del reco record rdse sett (adSearchForward) adSearchForward) o en dire direcci cción ón hacia hacia el princ princip ipio io del del reco record rdse sett adSearchBackward). La búsqueda termina al final o al principio del recordset, dependiendo (adSearchBackward). del valor de searchDirection . start la búsqueda.
(Opcional) Un marcador tipo BookMark que se utiliza como posición inicial de
El operador de comparación de criterio puede ser "> ">", "<", "=", ">=" , "<=", "<>" (distinto de) o "like" like" (coincidencia parcial de cadenas). cadenas). El valor de comparación puede ser ser una cadena, 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#"). #7/22/97#"). Si el operador de comparación es "like " 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 l ike ‘Es_’" o “Pais Like ‘Es*’ encuentra encuentra España España y Estonia)
ADO no tiene los métodos FindFirst, FindNext, FindNext, FindPrevious y FindLast. Deberá emplear 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 queremos exportar ese recordset hacia otra aplicación. Sintaxis
MiRecordset.Save MiRecordset.Save FileName, PersistFormat
FileName es la r uta uta completa del fichero en el que se guardará guardará el Recordset. Recordset. PersistFormat ( PersistFormat ( Opcional). Opcional). Un valor que especifica especifica el formato en que se guardará el Recordset. Puede ser una de las constantes siguientes.
ASCII
LSB
AdPersistADTG
(Valor (Valor predeterminado) Se guarda en un formato propietario (Advanced Data Tablegram). Tablegram). No es inteligible a simple vista, v ista, pero genera ficheros bastante cortos.
AAdPersistXML
Se guard guarda a en formato formato XML. Es un formato puramen puramente te en donde pueden verse los nombres de los campos y su
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 31
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 búsqueda mediante Seek es mucho más rápida que 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 presentar ningún ejemplo de este 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(ad MiRecordset1.Supports(adIndex) Index) = True Then Vea la ayuda de VB para mayor infor mación
Método NextRecordset Para Para enten entende derr este este método método es nece necesa sario rio explica explicarr previame previamente nte como como se pued puede e crear 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 recordse recordset, t, el recordse recordsett particular particular que va a estar activo es el correspond correspondient iente e a la primera sentencia SELECT. Mediante el método NextRecordset podemos ir avanzando a través de los siguientes recordsets recordsets particulares. El carácter de separación entre entre las sentencias SELECT SELECT es el punto y coma ( ; )
MiRecordset1.Open 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 método NextRecordset ese ese recordset recordset primero se borra borra y pasa pasa a ser ser recor recordse dsett actua actuall el cread creado o con la selecci selección ón segu segund nda a (Selec (Selectt * From From Regimen_Seguimiento Regimen_Seguimiento Where R s_Origen = 'LSB'") Set MiRecordset1 = MiRecordset1.NextRecordset MiRecordset1.NextRecordset Puede usar también este recordset recordset para crear un nuevo recordset a partir del primero pri mero Set MiRecordset2 = MiRecordset1.NextRecordset MiRecordset1.NextRecordset MiRecordset2 debe estar declarado como objeto recordset, y creado con la instrucción New: Set MiRecordset2 = New ADOBD.Recodset ADOBD.Recodset
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 32
La colección Fields de un recordset ADO Recordset. Contiene todos los objetos Field de un objeto Recordset.
Un objeto Recordset tiene una colección Fields que contiene todos los objetos Field. Field. Cada objeto Field se corresponde a una columna del Recordset. 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 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 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 pasaría si en vez de abrir el recordset le vamos añadiendo objetos objetos Field a su colección colecc ión Fields? Lo hacemos mediante el método Append: MiRecordset1.Fields.Append MiRecordset1.Fields.Append "MiCampo1", adBigInt MiRecordset1.Fields.Append MiRecordset1.Fields.Append "MiCampo2", adChar, adChar, 25 MiRecordset1.Fields.Append 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. nulo. Ya tenemos tenemos una estructura estructura de un recordse recordsett sin necesidad necesidad de haber 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 a mor" & vbCrLf & "Yo soy soy tu lobo" MiRecordset1.Update Ya tenemos tenemos un registro dentro dentro del recordse recordset. t. Podemos Podemos introducirle introducirle tantos tantos registros registros como quera queramo mos, s, y luego luego moverno movernos s por por el record recordse sett media mediante nte los los métod métodos os Movexxxx. Movexxxx. Ahora 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:
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 33
Y ahora vienen lo mejor. ¿Para que queremos un recordset que no tienen datos leídos desde una base base de datos? datos? Las aplicaciones aplicaciones de esto solamente 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 disponibles durante toda la aplicación, en v ez 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. MiRecordset.Fields.Append Name, Type, DefinedSize, Attrib
Sintaxis
Name Un String con el nombre del nuevo objeto Field, 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 adBigInt adBinary adBoolean adByRef adBSTR adChar adCurrency
adDate adDBDate adDBTime adDBTimeStamp adDecimal adDouble adEmpty adError adGUID adIDispatch adInteger
LSB
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). Un entero con signo de 8 bytes (DBTYPE_I8). Un valor binario (DBTYPE_BYTES). Un valor Boolean (DBTYPE_BOOL). 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). Una cadena de caracteres terminada en nulo (Unicode) (DBTYPE_BSTR). Un valor de tipo String (DBTYPE_STR). Un valor de tipo Currency (DBTYPE_CY). Un valor Currency valor Currency es un número de coma fija con cuatro dígitos a la derecha del signo signo decimal. Se almacena en un entero con signo de 8 bytes en escala de 10.000. Un valor de tipo Date (DBTYPE_DATE). (DBTYPE_DATE). Un v alor Date alor Date se almacena como un valor de tipo Double; Double; la parte entera es el número de días transcurridos desde desde el 30 de diciembre de 1899 y la parte f raccionaria es la fracción de un día. Un valor de fecha (aaaammdd (aaaammdd ) (DBTYPE_DBDATE). (DBTYPE_DBDATE). Un valor de hora (hhmmss ( hhmmss)) (DBTYPE_DBTIME). Una marca de fecha y hora (aaaammddhhmmss ( aaaammddhhmmss más una fracción de miles de millones) mi llones) (DBTYPE_DBTIMESTAMP). (DBTYPE_DBTIMESTAMP). Un valor numérico e xacto con una precisión y una escala escala fijas fij as (DBTYPE_DECIMAL). Un valor de coma f lotante de doble precisión (DBTYPE_R8). (DBTYPE_R8). No se ha especificado ningún valor ( DBTYPE_EMPTY). Un código de error de 32 bits (DBTYPE_ERROR). Un identificador único global (GUID) (DBTYPE_GUID). Un puntero a una interfaz Idispatch de un objeto OLE (DBTYPE_IDISPATCH). Un entero firmado de 4 bytes (DBTYPE_I4).
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 34
adIUnknown adLongVarBinary adLongVarChar adLongVarWChar adNumeric adSingle adSmallInt adTinyInt adUnsignedBigInt adUnsignedInt adUnsignedSmallInt adUnsignedTinyInt adUserDefined adVarBinary adVarChar adVariant adVector
adVarWChar adWChar
DefinedSize para un string) Attrib valores:
Un puntero a una interfaz Iunknown de un objeto OLE (DBTYPE_IUNKNOWN). Un valor binario largo (sólo para el objeto Parameter ). ). Un valor largo de tipo String (sólo para el objeto Parameter ). ). Un valor largo de tipo String terminado en nulo (sólo para el objeto Parameter ). ). Un valor numérico e xacto con una precisión y una escala escala exactas (DBTYPE_NUMERIC). Un valor de coma f lotante de simple precisión (DBTYPE_R4). Un entero con signo de 2 bytes (DBTYPE_I2). Un entero con signo de 1 byte (DBTYPE_I1). Un entero sin signo de 8 bytes (DBTYPE_UI8). Un entero sin signo de 4 bytes (DBTYPE_UI4). Un entero sin signo de 2 bytes (DBTYPE_UI2). Un entero sin signo de 1 byte (DBTYPE_UI1). Una variable definida por el usuario (DBTYPE_UDT). Un valor binario (sólo para el objeto Parameter ). ). Un valor de tipo String (sólo para el objeto Parameter ). ). Un tipo Variant de automatización (DBTYPE_VARIANT). (DBTYPE_VARIANT). Se une en una instrucción OR lógica con otro tipo para indicar que los datos son una 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). Una cadena de caracteres Unicode terminada en nulo (sólo para el objeto Parameter ). ). Una cadena de caracteres Unicode terminada en nulo (DBTYPE_WSTR).
Un Long que define el tamaño del campo si fuese necesario. (Por ejemplo
(Opcional). Especifica los atributos del campo a añadir. añadir. Puede tomar estos estos
adFldMayDefer adFldUpdatable adFldUnknownUpdatable adFldFixed adFldIsNullable adFldMayBeNull adFldLong
adFldRowID
adFldRowVersion adFldCacheDeferred
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. Indica que se puede escribir en el campo. Indica que el proveedor no puede determinar si se puede escribir en el campo. Indica que el campo contiene datos de longitud fija. Indica que el campo acepta valores Null. Null. Indica que se pueden leer valores Null del campo. Indica que se trata de un campo binario largo. También indica que se pueden utilizar los métodos AppendChunk AppendChunk y GetChunk. Indica que el campo contiene un identificador de fila persistente en el que no se puede puede escribir y que no tiene ningún valor significat ivo excepto la identificación de la fila (como por ejemplo un número de registro, un identificador único, etc.). Indica que el campo contiene algún ti po de marca de hora o de fecha que se utiliza para efectuar actualizaciones. 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. Fields.
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 35
Fields.Delete Field
Sintaxis
Field Un Variant que designa el objeto Field que se va a eliminar. Este parámetro tiene Field; no puede ser una posición ordinal o el propio objeto Field. Field. que ser el nombre del 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) MiRecordset.Fields.Item
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 siguie siguiente nte,, introd introducim ucimos os los nombr nombres es de todos todos los campos campos en un Combo ComboBox Box llamad llamado o ComboCampos Dim MM As String, I As Integer For I = 0 To MiRecordset1.Fields.Count - 1 MM = MiRecordset1.Fields.Item(I).Name ComboCampos.AddItem 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. Fields. Es un Long.
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 36
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 37
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 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, Recordset, para añadir o eli minar 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 CommandText Contiene el texto del comando que se quiere emitir al proveedor. Es un string. Suele ser una instru instrucci cción ón SQL, SQL, un nombr nombre e de tabla tabla o un proced procedimie imiento nto almace almacena nado, do, o cualq cualquie uierr otra otra instrucción que reconozca el proveedor. El val or predeterminado es una cadena cadena vacía. Propiedad CommandTimeout Especifica el intervalo de espera para que se ejecute un comando antes de que finalice el inten intento to y se genere genere un error. error. Es un Long que indica indica en segu segund ndos os ese tiempo tiempo.. El valor valor predeterminado es 30. Propiedad CommandType CommandType
(IMPORTANTE)
Indica el tipo t ipo de un objeto Command. Esta propiedad se usa para optimizar la eva luación de la propiedad CommandText, CommandText, ya que de esta forma el proveedor no tiene que perder tiempo examinando si es una instrucción SQL, un procedimiento al macenado 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, CommandText, ocurre un error cuando llama al método Execute. Valores posibles AdCmdText un
Indica que es una definición textual de un comando o una llamada a 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. adCmdStoredProc.
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 38
Propiedad Prepared Es un Booleano que indica si se debe guardar guardar una versión compilada de un comando antes de su ejecución. Esta propiedad fuerza al proveedor a guardar guardar una versión vers ió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, 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. True. Si no devuelve un error, simplemente ignora la solicitud de False. preparar el comando y establece la propiedad Prepared a False. Propiedad State Describe el estado del objeto: abierto o cerrado. Devuel ve un Long o una constante: adStateClosed o adStateOpen
Métodos del Objeto Command Método Execute
(IMPORTANTE, (IMPORT ANTE, más bien diríamos, el objetivo del Command)
Ejecuta la consulta, la instrucción SQL o el procedimiento almacenado especificado en la propiedad propiedad CommandText. CommandText. Devuelve un recordset o modifica la base de datos. Sintaxis Para un Command que devuelva filas: Set recordset = recordset = command .Execute(RecordsAffected Execute(RecordsAffected , Parameters, Parameters, Options) Para un Command que no devuelva filas: command .Execute RecordsAffected , Parameters, Parameters, Options command es 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 valor Long o una constante. Acepta estos valores adCmdText
Indica que el proveedor tiene que e valuar CommandText valuar CommandText como 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 e valuar CommandText valuar CommandText como como procedimiento almacenado. adCmdUnknown Indica que el tipo de comando en CommandText es CommandText es desconocido. adAsyncExecute Indica que el comando se tiene que ejecutar de fo rma 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
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 39
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). adAsyncFetch).
Comandos parametrizados. Los objetos Command pueden utilizar parámetros. De esta forma, podemos construir una consu consulta lta utiliza utilizand ndo o la interr interrog ogaci ación ón (?) como como comodí comodín. n. Así cada cada vez que que ejecu ejecutem temos os el comando, V.B. se encargará de sustituir el comodín por los parámetros asociados a dicho command. command. Además podemos utilizar los parámetros para recoger los va lores 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 ConexBDPrensa As ADODB.Connection Dim RsBDPrensa1 RsBDPrensa1 As ADODB.Recordset Dim StrIntroducir StrIntr oducir As String, NumeroDocumento as long long Rem Se abre un objeto Connection para crear sobre él el recordset Set ConexBDPrensa = New ADODB.Connection ADODB.Connection ConexBDPrensa.Connection ConexBDPrensa.ConnectionString String = "Provider=MSDAORA.1;” & _ “User ID=INTRANET;Passw ID=INTRANET;Password=INTRANET ord=INTRANET;Data ;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 RsBDPrensa1.Open "Int_Documentos Order By CL_DOC", ConexBDPrensa, adOpenDynamic, adLockOptimistic RsBDPrensa1.MoveLast NumeroDocumento NumeroDocumento = RsBDPrensa1!CL_DOC RsBDPrensa1!CL_DOC NumeroDocumento NumeroDocumento = NumeroDocumento NumeroDocumento + 1 RsBDPrensa1.Close (* Este es el punto punto donde cambia el código que que verá más adelante) Rem Se introduce en una una variable tipo String una instrucción para añadir añadir un nuevo registro Rem Esa instrucció instrucción n se va a ejecutar ejecutar desde el objeto Conne Connection ction mediante mediante su método Execute
StrIntroducir = "Insert Into INT_DOCUMENTOS " & _ "(CL_DOC,NOM_DOC,TITULO_DOC,AUTOR_DOC,CL_T "(CL_DOC,NOM_DOC,TITULO _DOC,AUTOR_DOC,CL_TEMA_DOC,CL_DPT_ EMA_DOC,CL_DPT_DOC,” DOC,” & _ “CL_TIPO_DOC,FICH_DOC,FECHA_EMISION_DOC,UL “CL_TIPO_DOC,FICH_DOC,FECHA_E MISION_DOC,ULTIMA_HORA_DOC,” TIMA_HORA_DOC,” & _ VISIBLE_DOC) Values Values (" & NumeroDocumento & ",'" & TbTitulo & "','" & TbTitulo & _ "','" & TbTitulo.Tag TbTitulo.Tag & "',19,2,1,'" & HRefPrensa & "/" & TbNombFichTIF & "','" & Date & "',0,1)" Rem Observe que los valores tipo string introducidos (TbXXX) (TbXXX) van entre comilla simple Rem Se ejecuta esa esa instrucción instruc ción desde el objeto Connection ConexBDPrensa ConexBDP rensa
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 40
ConexBDPrensa.Execute 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 una base base de dato datos. s. Se introd introduce uce un nuevo nuevo regist registro ro en la tabla tabla INT_DO INT_DOCUM CUMENT ENTOS. OS. El resumen de prensa prensa es un fichero .Tiff de nombre TbNombFichTIF 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 intr oducir 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, NOM_DOC TITULO_DOC AUTOR_DOC CL_TEMA_DOC CL_DPT_DOC CL_TIPO_DOC FICH_DOC
NumeroDocumento (Long ca calculado) TbTitulo (String contenido en TbTitulo.Text) TbTitulo (String contenido en TbTitulo.Text – se repite-) TbTitulo.Tag (String contenido en TbTitulo.Tag) 19 (Integer, dato f ijo) 2 (Integer, dato f ijo) 1 (Integer, dato f ijo) HRefPrensa & "/" & TbNombFic FichTIF 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 introducir los datos, método método que los lingüistas lingüistas especializa especializados dos en la jerga informática 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. AddNew. Tiene la gran gran ventaja de que la acepta cualquier base base de datos, datos, indepen independien dientement temente e de donde donde esté el cursor cursor.. Habrá Habrá observado observado que utilizamos el método método Execute del objeto Connection. Y así funciona perfectamente. Vamos a hacer lo mismo, pero Command, (Que pertenece introduciendo la cadena de caracteres un objeto Command, pertenece al mismo objeto 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. antes. Aquí Aquí comienza el cambio del código) Dim MiComando As ADODB.Command Set MiComando = New ADODB.Command ADODB.Command MiComando.ActiveConnection = ConexBDPrensa ConexBDPrensa MiComando.CommandText = "Insert Into INT_DOCUMENTOS " _ MiComando.CommandText & "(CL_DOC,NOM_DOC,TITULO_DOC,AUTOR_DOC,CL_T "(CL_DOC,NOM_DOC,TITULO _DOC,AUTOR_DOC,CL_TEMA_DOC,CL_DPT_ EMA_DOC,CL_DPT_DOC,CL_TIP DOC,CL_TIP O_DOC,FICH_DOC,FECHA_EMISION_DOC,ULTIMA_HORA_DOC,VISIBLE_DOC) O_DOC,FICH_DOC,FECHA_EMISION_DOC,UL TIMA_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.
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 41
¿Entonces, para para que existe? La respuesta respuesta es es sencilla: facilita la comprensión del código. código. Pero que el objeto Command no le perjudique precisamente eso, la comprensión del código. No se preocu preocupe pe de no ser ser estric estrictam tamen ente te académ académico ico.. Este Este humild humilde e autor autor nunca nunca usa usa Comman Command d 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 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 adUseClient (Lado cliente) y de esta forma los cursores creados para 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: Recordset: RsBDPrensa.Open RsBDPrensa.Open "Int_Documentos", ConexBDPrensa, adOpenDynamic, adOpenDynamic, adLockOptimistic adLockOptimistic Ejecutamos el método AddNew AddNew RsBDPrensa.AddNew Metemos los datos RsBDPrensa!CL_DOC RsBDPrensa!CL_DOC = NumeroDocumento NumeroDocumento RsBDPrensa!NOM_DOC = TbTitulo RsBDPrensa!TITULO_DOC = TbTitulo RsBDPrensa!AUTOR_DOC = TbTitulo.Tag RsBDPrensa!CL_TEMA_DOC RsBDPrensa!CL_TEMA_DOC = 19 RsBDPrensa!FECHA_EMISION_DOC RsBDPrensa!FECHA_EMISION_DO C = Date RsBDPrensa!CL_DPT_DOC RsBDPrensa!CL_DPT_DOC = 2 RsBDPrensa!CL_TIPO_DOC RsBDPrensa!CL_TIPO_DOC = 1 RsBDPrensa!FICH_DOC = HRefPrensa & "/" & TbNombFichTIF RsBDPrensa!VISIBLE_DOC = 1 RsBDPrensa!ULTIMA_HORA_DOC 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 programadores se rinden cuando cuando ven que no les funciona los métodos métodos AddN AddNew ew / Upda Update te para para intro introdu ducir cir nuevo nuevos s datos datos.. Cierto Cierto es que que cada cada base base de datos 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 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
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 42
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. Componentes. La apariencia 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. BOFAction. Establece la forma de proceder cuando llega a la fila anterior a la primera. Toma uno de estos valores: 0 – adDoM DoMoveF oveFir irst st 1 – adDoStayBOF
Vuelve elve a la prime rimera ra fila fila Perma rmanece en la fil fila BO BOF
Propiedad CommandType CommandType Es idéntica a la misma propiedad del objeto Command. Acepta los valores: AdCmdText un
Indica que es una definición textual de un comando o una llamada a 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 CursorType Es la misma m isma que para el objeto Recordset. Acepta los valores: 1 – adOpenKeyset 2 - adOpenDynamic adOpenDynamic 3 – adOpenStatic
Propiedad EOFAction
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 43
Establece la forma de proceder cuando cuando llega a la fila EOF. EOF. Acepta los valores: 0 – adDoM DoMove oveLast 1 – adStayEOF 2 – adDoAddNew
Vuelve elve a la últim ltima a fila fila Permanece en la fila EOF Añade una nueva fil fila
Propiedad Lock Type Type Tipo de Bloque. Igual a la m isma 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 propieda propiedad d es de lectura lectura y escritura escritura.. El valor de la propieda propiedad d Passw Password ord 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 Actu Actuali aliza za la inform informaci ación ón de los contr control oles es enla enlaza zado dos s a dato datos. s. UpdateRecords.
No exis existe te el métod método o
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 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.
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 44
Control
ADO
RDO
DAO
Referenc ia
DBGrid DataGrid DataList DataCombo DBList DBCombo MSFlexGrid MSHFlexGrid
NO SI SI SI SI SI NO SI
SI NO SI SI SI SI SI NO
SI NO SI SI SI SI SI NO
Microsoft Data Bound Grid Control 5.0 SP3 Microsoft DataGrid Control 6.0 (OLEDB) Microsoft Data List Controls 6.0 (OLEDB) Microsoft Data List Controls 6.0 (OLEDB) Microsoft Data Bound List Controls 6.0 Microsoft Data Bound List Controls 6.0 Microsoft FlexGrid Control 6.0 Microsoft Hi Hierarchical FlexGrid Control 6. 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 aprend aprender er a programar programar con esta tecnologí tecnología. 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 serv idor 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.
Agrad Agradecim ecimient ientos. os. En este capí capítulo tulo par particip ticipó ó activ activame amente nte mi alum alumno no del CEU Cés César ar Mor Moreno eno Fernández.
LSB
Visual Basic Guía del Estudiante
Capítulo Capítul o 14
Página 45