Acceso A Datos Con ADO

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 21

Acceso a datos con ADO .

NET
En los siguientes temas vamos a tratar el acceso a datos desde VB.NET, haciendo uso del nuevo modelo de acceso a datos incluido en la plataforma .NET Framework: ADO .NET. Mostraremos las tareas bsicas para el acceso a datos desde aplicaciones basadas en formularios Windows, empleando la tecnologa proporcionada por ADO .NET. ADO .NET es la nueva versin del modelo de objetos ADO (ActiveX Data Objects), es decir, la estrategia que ofrece Microsoft para el acceso a datos. ADO .NET ha sido ampliado para cubrir todas las necesidades que ADO no ofreca, y est diseado para trabajar con conjuntos de datos desconectados, lo que permite reducir el trfico de red. ADO .NET utiliza XML como formato universal de transmisin de los datos. ADO .NET posee una serie de objetos que son los mismos que aparecen en la versin anterior de ADO, como pueden ser el objeto Connection o Command, e introduce nuevos objetos tales como el objeto DataReader, DataSet o DataView. ADO .NET se puede definir como: Un conjunto de interfaces, clases, estructuras y enumeraciones que permiten el acceso a datos desde la plataforma .NET de Microsoft La evolucin lgica del API ADO tradicional de Microsoft Permite un modo de acceso desconectado a los datos, los cuales pueden provenir de mltiples fuentes de datos, de diferente arquitectura de almacenamiento

Soporta un completo modelo de programacin y adaptacin, basado en el estndar XML

Seguidamente vamos a realizar una descripcin genrica de la arquitectura de ADO .NET, y ms tarde veremos como utilizarlo desde aplicaciones VB.NET

Comparativa de ADO /ADO .NET


Como punto de partida para comprender la importancia del nuevo diseo de ADO .NET, analizaremos los aspectos distintivos entre ADO .NET y el modelo ADO vigente hasta la fecha. Las diferencias existentes son muchas, y van desde el mismo diseo de los interfaces de las clases, hasta el nivel estructural de los componentes, pasando por el modo en cmo manejan la informacin. La Tabla 31 muestra estas diferencias. El modelo de objetos de ADO .NET es mucho ms rico que el de ADO. Incorpora nuevas clases de datos y encapsula mucha ms potencia de uso a la par que corrige pequeos defectos de las versiones anteriores. Aprovechando la nueva arquitectura de servicios de la plataforma .NET, ADO .NET puede ser usado como un servicio del sistema, pudiendo ser utilizado por cualquier aplicacin escrita en cualquier lenguaje. En ADO .NET se emplea el DataSet, mientras que en ADO se emplea el Recordset. No es slo un cambio de nombre. En memoria y en rendimiento las cosas han cambiado mucho. Un Recordset de ADO slo puede contener un nico resultado (fruto de consultas complejas o no). En cambio, un DataSet puede representar un espacio de mltiples tablas simultneamente. Esto permite obtener una representacin de espejo de la base de datos a la que representa. En ADO slo nos podemos mover secuencialmente fila a fila. En ADO .NET podremos navegar por filas en un DataSet, y consecuentemente avanzar en una fila/conjunto de filas de otro DataSet asociado a travs de una coleccin de relaciones.

Clases de objetos mas estructuradas

Independiente del lenguaje

Representaciones en memoria de los datos

Nmero de tablas

Navegacin mejorada

Acceso a datos Off-line (Desconectados)

En ADO .NET todos los accesos a datos se realizan en contextos desconectados de la base de datos. En ADO, es posible tener estructuras desconectadas, pero es una eleccin a tomar. Por defecto, ADO est pensado para contextos con conexin. Adems, ADO .NET realiza todos los accesos a los servicios de datos a travs del objeto DataSetCommand, lo que permite personalizar cada comando en funcin del rendimiento y la necesidad del programa (en ADO, el Recordset puede modificar datos a travs de su API de cursores, lo que muchas veces no es ptimo).

Compartimiento de datos entre capas, o bien, El traspaso de un recordset Off-line en ADO es ms complejo y pesado pues es necesario entre componentes establecer un vnculo RPC y un proceso de COM marshalling (verificacin de tipos de datos remotos). En ADO .NET para la comunicacin entre componentes y capas se emplea un simple stream XML. Tipos de datos ms ricos Debido al COM Marshalling los tipos de datos que se pueden usar va RPC estn muy limitados. En ADO .NET, gracias a los flujos XML, es posible enviar cualquier tipo de dato de manera sencilla. Tanto ADO como ADO .NET requieren de muchos recursos cuando se habla de envos masivos de datos. El stress del sistema es proporcional al nmero de filas que se quieren procesar. Pero ADO .NET permite utilizar mucho ms eficientemente los recursos, pues no tiene que realizar el COM Marshalling de datos, en lo que ADO s (y eso supone un canal ms de envo de datos de control que ADO .NET ahorra). Por motivos de seguridad, las empresas suelen bloquear los sistemas de comunicaciones va RPC. O bien, implementan pesados mecanismos de control de acceso y envo de la informacin. Lo que complica los diseos, sus rendimientos y su instalacin y distribucin. En ADO .NET, puesto que no se realizan llamadas al sistema, sino que se envan flujos de datos en XML, se simplifica enormemente la configuracin de estos dispositivos.
Tabla 31

Rendimiento

Penetracin de firewalls

De los anteriores puntos podemos obtener muy buenas conclusiones en cuanto a las mejoras introducidas en el nuevo modelo ADO .NET. Se puede resumir en un mejor mecanismo de comunicacin entre procesos gracias a XML y una independencia del cliente con respecto al servidor, que posibilita el funcionamiento autnomo de la aplicacin (mejor tolerancia a fallos, independencia del estado de la red).

Beneficios de ADO .NET


ADO .NET ofrece una buena cantidad de mejoras respecto a modelos anteriores de ADO. Los beneficios los podemos agrupar en las categoras descritas a continuacin.

Interoperabilidad
Las aplicaciones basadas en ADO .NET obtienen ventaja de la flexibilidad y la masiva aceptacin del estndar XML para el intercambio de datos. Puesto que XML es el estndar de envo de informacin entre capas, cualquier componente capaz de Interpretar los datos XML puede acceder a la informacin de ADO .NET, se encuentre donde se encuentre, y procesarla. Adems, puesto que la informacin se enva en flujos de XML, no importa la implementacin empleada para enviar o recoger la informacin as como la plataforma empleada-. Simplemente se exige a los componentes que reconozcan el formato XML empleado para el proceso, envo y recepcin de un DataSet.

Mantenimiento
En el ciclo de vida de una aplicacin los cambios poco sustanciales y modestos son permisibles. Pero cuando es necesario abordar un cambio estructural o arquitectnico del sistema, la tarea se vuelve demasiado compleja y a veces inviable. Esto es una gran desventaja de los sistemas actuales, pues muchas veces se trata de una cuestin de actualizacin de los procesos de la propia empresa. Adems, cuanto ms se aumenta el proceso de la operativa de la empresa, las necesidades de proceso crecen hasta desbordar las mquinas. Es por ello que se separa la estructura de un programa en varias capas. Una de esas capas es la de datos, que es fundamental desarrollar correctamente. Gracias a los DataSets, la tarea de portar y aumentar los procesos de datos y de negocio ser mas sencillo: el intercambio de informacin a travs de XML, hace que sea ms sencilla la tarea de estructurar en ms capas la aplicacin, convirtindola en ms modular y fcil de mantener.

Programacin
Los programadores pueden acceder a un API de programacin estructurado, de fuerte tipificado y que adems se concentra en la correcta forma de presentar los datos. Centra en la estructura del lenguaje lo que un programador necesita para disear los programas sin dar muchos rodeos. El Cdigo fuente 557 muestra un ejemplo de cdigo sin tipificar:

.... If CosteTotal > Table("Cliente")("Luis").Column("CreditoDisponible") Then .... Cdigo fuente 557

Como se puede observar, aparecen nombres de objetos genricos del sistema que complican la lectura del cdigo, a la par que los operadores complican tambin la visin de la secuencia de acceso a los datos. Podramos interpretar lo que hace gracias a que aparecen los nombres propios de los datos que necesitamos. El Cdigo fuente 558 muestra un ejemplo un poco ms tipificado:

.... If CosteTotal > DataSet1.Cliente("Luis").CreditoDisponible Then .... Cdigo fuente 558

El ejemplo es exactamente igual al anterior, pero en este caso, el cdigo se centra ms en los objetos reales que en el objeto del lenguaje en s: las palabras Table y Column ya no aparecen. En su lugar vemos que aparecen los nombres de los objetos empleados de la vida real, lo que hace el cdigo ms legible. Si a esto unimos que los entornos ya son capaces de ayudarnos a escribir el cdigo, todava lo tenemos ms sencillo, ya que podemos ver con nuestras palabras el modelo de objetos de datos que necesitamos en cada momento. Incluso a nivel de ejecucin nos vemos respaldado por un sistema de control de tipos y errores que nos permitirn proporcionar una robustez innata, que antes no se tena sin pasar por el uso de funciones externas.

Rendimiento
Puesto que trabajamos con objetos de datos desconectados, todo el proceso se acelera, ya que no tenemos que estar comunicndonos por Marshalling con el servidor. Adems, gracias al modelo de XML la conversin de tipos no es necesaria a nivel de COM. Se reduce pues el ancho de banda disponible, se independiza ms el cliente del servidor, y se descarga ms a ste, que puede estar dedicado a otras tareas en lo que el cliente analiza sus datos.

Escalabilidad
Las aplicaciones Web tienen un nmero ilimitado de conexiones potenciales debido a la naturaleza de Internet. Los servidores son capaces de atender muy bien decenas y decenas de conexiones. Pero cuando hablamos de miles y millones, los servidores ya no son capaces de realizar correctamente su trabajo. Esto es debido a que por cada usuario se mantiene una memoria de proceso y conexin, un conjunto de bloqueos de recursos como puedan ser tablas, ndices, etc., y una comprobacin de sus permisos; todo ello consume tiempo y recursos. ADO .NET favorece la escalabilidad, puesto que su modelo de conexin Off-Line evita que se mantengan los recursos reservados ms tiempo del considerado necesario. Esto permite que ms usuarios por unidad de tiempo puedan acceder a la aplicacin sin problemas de tiempos. Adems se pueden montar servicios en Cluster de alta disponibilidad que sern balanceados automticamente por el sistema sin afectar a las conexiones ADO. Lo cual garantiza la ampliacin del servicio sin representar un cambio de arquitectura de diseo.

Arquitectura de datos desconectados


ADO .NET est basado en una arquitectura desconectada de los datos. En una aplicacin de datos se ha comprobado que mantener los recursos reservados mucho tiempo, implica reducir el nmero de

usuarios conectados y aumenta el proceso del sistema al mantener una poltica de bloqueos y transacciones. Al mismo tiempo, si la aplicacin mantiene ms de un objeto simultneamente, se encuentra con el problema de tener que estar continuamente conectando con el servidor para alimentar las relaciones existentes entre ambas, subiendo y bajando informacin va RPC. Con ADO .NET se consigue estar conectado al servidor slo lo estrictamente necesario para realizar la operacin de carga de los datos en el DataSet. De esta manera se reducen los bloqueos y las conexiones a la mnima expresin. Se pueden soportar muchos ms usuarios por unidad de tiempo y disminuyen los tiempos de respuesta, a la par que se aceleran las ejecuciones de los programas. Tradicionalmente, el recoger informacin de una base de datos ha ido destinado a realizar un proceso con dicha informacin: mostrarla por pantalla, procesarla o enviarla a algn componente. Frecuentemente, la aplicacin no necesita una nica fila, sino un buen conjunto de ellas. Adems, tambin frecuentemente, ese conjunto de filas procede no de una tabla sino de una unin de mltiples tablas (join de tablas). Una vez que estos datos son cargados, la aplicacin los trata como un bloque compacto. En un modelo desconectado, es inviable el tener que conectar con la base de datos cada vez que avanzamos un registro para recoger la informacin asociada a ese registro (condiciones del join). Para solucionarlo, lo que se realiza es almacenar temporalmente toda la informacin necesaria donde sea necesario y trabajar con ella. Esto es lo que representa un DataSet en el modelo ADO .NET. Un DataSet es una cach de registros recuperados de una base de datos que acta como un sistema de almacenamiento virtual, y que contiene una o ms tablas basadas en las tablas reales de la base de datos. Adicionalmente, almacena las relaciones y reglas de integridad existentes entre ellas para garantizar la estabilidad e integridad de la informacin de la base de datos. Muy importante es recalcar, que los DataSets son almacenes pasivos de datos, esto es, no se ven alterados ante cambios subyacentes de la base de datos. Es necesario recargarlos siempre que queramos estar al da, en cuanto a datos se refiere. Una de las mayores ventajas de esta implementacin, es que una vez obtenido el DataSet, ste puede ser enviado (en forma de flujo XML) entre distintos componentes de la capa de negocio, como si de una variable ms se tratase, ahorrando as comunicaciones a travs de la base de datos. Una consecuencia lgica de este tipo de arquitecturas, es la de conseguir que los DataSets sean independientes de los orgenes de datos. Los drivers OLE-DB transformarn la consulta SQL en un cursor representado con una estructura XML, que es independiente del motor de la base de datos. Esto nos permitir trabajar con mltiples orgenes de datos, de distintos fabricante e incluso en formatos que no pertenezcan a bases de datos, por ejemplo, ficheros planos u hojas de clculo, lo que representa un importante punto de compatibilidad y flexibilidad. Si a esto unimos el hecho de que disponemos de un modelo consistente de objetos (xmlDOM) que es independiente del origen de datos, las operaciones de los DataSets no se vern afectadas por dicho origen. La persistencia es un concepto muy interesante en el mundo del desarrollo. Es un mecanismo por el cual un componente puede almacenar su estado (valores de variables, propiedades, datos...en un momento concreto del tiempo) en un soporte de almacenamiento fijo. De manera, que cuando es necesario, se puede recargar el componente tal y como qued en una operacin anterior. En un sistema de trabajo Off-Line como el que plantea ADO .NET, la persistencia es un mecanismo fundamental. Podemos cerrar la aplicacin y mantener persistentes todos los DataSets necesarios, de manera que al reiniciarla, nos encontramos los DataSets tal y como los dejamos. Ahorrando el tiempo que hubiera sido necesario para recuperar de nuevo toda esa informacin del servidor. Optimizando todava ms el rendimiento del sistema distribuido.

El formato que emplea ADO .NET para almacenar su estado es XML. Puesto que ya es un estndar de la industria, esta persistencia nos ofrece las siguientes cualidades: La informacin puede estar accesible para cualquier componente del sistema que entienda XML. Es un formato de texto plano, no binario, que lo hace compatible con cualquier componente de cualquier plataforma, y recuperable en cualquier circunstancia.

DataSet
El API de ADO .NET proporciona una superclase, DataSet, que encapsula lo que sera la base de datos a un nivel lgico: tablas, vistas, relaciones, integridad entre todos ellos, etc., pero siempre con independencia del tipo de fabricante que la dise. Aqu se tiene el mejor concepto de datos desconectados: una copia en el cliente de la arquitectura de la base de datos, basada en un esquema XML que la independiza del fabricante, proporcionando al desarrollador la libertad de trabajo independiente de la plataforma. La Figura 339 muestra una representacin de este tipo de objeto.

Figura 339. Esquema de un DataSet.

Esta clase se compone a su vez, de clases de soporte, que representan cada una, los elementos arquitecturales de la base de datos: tablas, columnas, filas, sus reglas de chequeo, sus relaciones, las vistas asociadas a la tabla, etc.

ADO .NET y XML


XML se ha convertido en la piedra angular de la informtica distribuida de nuestros das. De ah que gran parte de las motivaciones en cuanto a la redefinicin del API de ADO, se deban a la adaptacin de los objetos a un modelo de procesos que se apoya en documentos XML, no en objetos especficos de cada plataforma a partir de cursores. Esto permite que las clases de ADO .NET puedan implementar mecanismos de conversin de datos entre plataformas, lectura de datos de cualquier origen, habilitar mecanismos de persistencia en el mismo formato en el que se procesan., etc. En esta redefinicin, Microsoft ha puesto como intermediario entre un cliente y sus datos, un adaptador que transforma cada comando y cada dato en modelos de documentos XML. Tanto para consultas como para actualizaciones. Esto es lo que posibilita la nueva filosofa de acceso a datos desconectados de ADO .NET: primero se cargan en el cliente los documentos necesarios almacenndolos en DataSet, a partir de consultas a tablas, vistas, procedimientos, etc.; se nos da la posibilidad de trabajar con documentos, sin necesidad de estar continuamente consumiendo recursos de la red; y por ltimo, se procesarn los cambios producidos envindolos a la base de datos, el

adaptador tomar los cambios del documento, y los replicar al servidor. En la Figura 340 se puede ver un esquema de la relacin entre ADO .NET y XML.

Figura 340. Esquema de relacin entre ADO .NET y XML.

Una visin general de ADO .NET


ADO .NET es el modelo de objetos para el acceso a datos incluido en la jerarqua de clases de la plataforma .NET Framework. Se trata de una evolucin de ADO, el anterior modelo para la gestin de datos, incluido en VB6. ADO .NET ha sido ampliado para cubrir todas las necesidades que ADO no ofreca. Est diseado para trabajar con conjuntos de datos desconectados, lo que permite reducir el trfico de red, utilizando XML como formato universal de transmisin de los datos. ADO .NET posee una serie de objetos que son los mismos que aparecen en la versin anterior de ADO, como pueden ser el objeto Connection o Command, e introduce nuevos objetos tales como el objeto DataReader, DataSet o DataView. A continuacin vamos a comentar brevemente los objetos principales que posee ADO .NET. Los espacios de nombre que utiliza ADO .NET son principalmente System.Data y System.Data.OleDb o System.Data.SqlClient. System.Data ofrece las facilidades de codificacin para el acceso y manejo de datos, mientras que System.Data.OleDb y System.Data.SqlClient contienen los proveedores; en el primer caso, los proveedores genricos de OLE DB, y en el segundo, los proveedores nativos de SQL Server que ofrece la plataforma .NET. Para el lector que haya seguido la evolucin de la plataforma .NET, debemos puntualizar que estos espacios de nombres se denominaban System.Data.ADO y System.Data.SQL en la Beta 1 de la plataforma .NET. El objeto Connection define el modo en cmo se establece la conexin con el almacn de datos. .NET Framework ofrece dos objetos Connection: SqlConnection y OleDbConnection, que se corresponden con las dos posibilidades de proveedores que disponemos. Otro objeto importante dentro del modelo de objetos de ADO .NET es el objeto System.Data.DataSet (conjunto de datos). Este nuevo objeto representa un conjunto de datos de manera completa, pudiendo incluir mltiples tablas junto con sus relaciones. No debemos confundir el nuevo objeto DataSet con el antiguo objeto Recordset; el objeto DataSet contiene un conjunto de tablas y las relaciones entre las mismas, sin embargo el objeto Recordset contiene nicamente una tabla. Para acceder a una tabla determinada el objeto DataSet ofrece la coleccin Tables. Para poder crear e inicializar las tablas del DataSet debemos hacer uso del objeto DataAdapter, que igualmente, posee las dos versiones, es decir, el objeto SqlDataAdapter para SQL Server y

OleDbDataAdapter genrico de OLE DB. En la Beta 1 de la plataforma .NET el objeto DataAdapter se denominaba DataSetCommand. Al objeto DataAdapter le pasaremos como parmetro una cadena que representa la consulta que se va a ejecutar y que va a rellenar de datos el DataSet. Del objeto DataAdapter utilizaremos el mtodo Fill(), que posee dos parmetros, el primero es el objeto DataSet que vamos rellenar con datos, y el segundo es una cadena que identifica el objeto DataTable (tabla) que se va a crear dentro del objeto DataSet como resultado de la ejecucin de la consulta Un DataSet puede contener diversas tablas, que se representan mediante objetos DataTable. Para mostrar el contenido de un DataSet, mediante Data Binding, por ejemplo, necesitamos el objeto DataView. Un objeto DataView nos permite obtener un subconjunto personalizado de los datos contenidos en un objeto DataTable. Cada objeto DataTable de un DataSet posee la propiedad DefaultView, que devuelve la vista de los datos por defecto de la tabla. Otro objeto de ADO .NET es DataReader, que representa un cursor de slo lectura y que slo permite desplazamiento hacia adelante (read-only/forward-only), cada vez existe un nico registro en memoria, el objeto DataReader mantiene abierta la conexin con el origen de los datos hasta que es cerrado. Al igual que ocurra con otros objetos de ADO .NET, de este objeto tenemos dos versiones, que como el lector sospechar se trata de los objetos SqlDataReader y OleDbDataReader.

Espacios de nombres y clases en ADO .NET


En el presente apartado vamos a enumerar brevemente los principales elementos que forman parte del API de ADO .NET. Primero vamos a comentar los distintos espacios de nombres que constituyen la tecnologa ADO .NET: System.Data. Clases genricas de datos de ADO .NET. Integra la gran mayora de clases que habilitan el acceso a los datos de la arquitectura .NET. System.Data.SqlClient. Clases del proveedor de datos de SQL Server. Permite el acceso a proveedores SQL Server en su versin 7.0 y superior. System.Data.OleDb. Clases del proveedor de datos de OleDB. Permite el acceso a proveedores .NET que trabajan directamente contra controladores basados en los ActiveX de Microsoft. System.Data.SqlTypes. Definicin de los tipos de datos de SQL Server. Proporciona la encapsulacin en clases de todos los tipos de datos nativos de SQL Server y sus funciones de manejo de errores, ajuste y conversin de tipos, etc. System.Data.Common. Clases base, reutilizables de ADO .NET. Proporciona la coleccin de clases necesarias para acceder a una fuente de datos (como por ejemplo una Base de Datos). System.Data.Internal. Integra el conjunto de clases internas de las que se componen los proveedores de datos.

Dentro del espacio de nombres System.Data encontramos las siguientes clases compartidas, que constituyen el eje central de ADO .NET.

DataSet. Almacn de datos por excelencia en ADO .NET. Representa una base de datos desconectada del proveedor de datos. Almacena tablas y sus relaciones. DataTable. Un contenedor de datos. Estructurado como un conjunto de filas (DataRow) y columnas (DataColumn). DataRow. Registro que almacena n valores. Representacin en ADO .NET de una fila/tupla de una tabla de la base de datos. DataColumn. Contiene la definicin de una columna. Metadatos y datos asociados a su dominio. DataRelation. Enlace entre dos o ms columnas iguales de dos o mas tablas. Constraint. Reglas de validacin de las columnas de una tabla. DataColumnMapping. Vnculo lgico existente entre una columna de un objeto del DataSet y la columna fsica de la tabla de la base de datos. DataTableMapping. Vnculo lgico existente entre una tabla del DataSet y la tabla fsica de la base de datos.

Adems de estas clases, existe otro grupo de clases consistente en las clases especficas de un proveedor de datos. Estas clases conforman los aspectos particulares de un fabricante de proveedores
de datos .NET. Tienen una sintaxis con el formato XXXClase, donde XXX es un prefijo que determina el tipo de plataforma de conexin a datos. Se definen en dos espacios de nombre: System.Data.SqlClient y System.Data.OleDb. En la Tabla 32 se ofrece una descripcin de las clases que podemos encontrar en estos espacios de nombre. Clase SqlCommand OleDbCommand SqlConnection OleDbConnection SqlCommandBuilder OleDbCommandBuilder SqlDataReader OleDbDataReader Un lector de datos de slo avance, conectado a la base de datos. Generador de comandos SQL de insercin, modificacin y borrado desde una consulta SQL de seleccin de datos. Clase que representa la etapa de conexin a un proveedor de datos. Encapsula la seguridad, pooling de conexiones, etc. Descripcin Clases que representan un comando SQL contra un sistema gestor de datos.

SqlDataAdapter OleDbDataAdapter SqlParameter OleDbParameter SqlTransaction OleDbTransaction

Clase adaptadora entre un objeto DataSet y sus operaciones fsicas en la base de datos (select, insert, update y delete).

Define los parmetros empleados procedimientos almacenados.

en la llamada a

Gestin de las transacciones a realizar en la base de datos.

Tabla 32

Para aquellos conocedores de ADO en alguna de sus versiones anteriores, podemos hacer una analoga o comparacin entre las antiguas clases de ADO y las nuevas de ADO .NET. En la Figura 341 se puede ver esta aproximacin.

Figura 341. Comparativa entre las clases de ADO y ADO .NET.

Hasta aqu hemos realizado una introduccin a la tecnologa ADO .NET, repasando su arquitectura y comentando las clases principales. En lo que resta de tema vamos a utilizar las distintas clases que nos ofrece ADO .NET desde VB.NET, para realizar tareas comunes de acceso a datos, como pueden ser establecer una conexin, obtener un conjunto de registros, realizar operaciones con los datos, etc.

Las clases Connection


En los ejemplos con datos que vamos a realizar, se ha utilizado SQL Server 2000 como servidor de datos, y fundamentalmente, la base de datos Northwind. El primer paso obligado en un acceso a datos consiste en establecer una conexin con un almacn de datos. Esto lo vamos a conseguir gracias a las clases Connection de ADO .NET, que nos permitirn conectarnos a un origen de datos (ya sea una base de datos o no) , al igual que en ADO clsico emplebamos el objeto Connection.

En ADO se poda ejecutar directamente una sentencia contra el almacn de datos, o bien abrir un conjunto de registros (Recordset), pero en ADO .NET no vamos a realizar esta operacin con este tipo de objetos. Debemos recordar que existen dos implementaciones para algunos de los objetos de ADO .NET, cada uno especfico del origen de datos con el que nos vamos a conectar. Esto ocurre con el objeto Connection, que tiene dos versiones, una como proveedor de datos de SQL Server, a travs de la clase System.Data.SqlClient.SqlConnection, y otra como proveedor de datos OLEDB, a travs de la clase Sysem.Data.OleDb.OleDbConnection. Por norma general, del objeto Connection utilizaremos los mtodos Open( ) y Close( ), para abrir y cerrar conexiones respectivamente, con el almacn de datos adecuado. Aunque tenemos el recolector de basura que gestiona de forma automtica los recursos y objetos que no son utilizados, es recomendable cerrar las conexiones de forma explcita utilizando el mtodo Close( ). Las conexiones se abrirn de forma explcita utilizando el mtodo Open(), pero tambin se puede hacer de forma implcita utilizando un objeto DataAdapter, esta posibilidad la veremos ms adelante. Cuando ejecutamos el mtodo Open() sobre un objeto Connection (SqlConnection o OleDbConnection), se abrir la conexin que se ha indicado en su propiedad ConnectionString, es decir, esta propiedad indicar la cadena de conexin que se va a utilizar para establecer la conexin con el almacn de datos correspondiente. El mtodo Open() no posee parmetros. El constructor de la clase Connection (al decir clase Connection de forma genrica nos estamos refiriendo en conjunto a las clases SqlConnection y OleDbConnection de ADO .NET) se encuentra sobrecargado, y en una de sus versiones recibe como parmetro una cadena que ser la cadena de conexin que se aplique a su propiedad ConnectionString. Si hacemos uso de la clase SqlConnection, en la cadena de conexin no podremos especificar una DSN de ODBC, ya que la conexin se va a realizar en este caso directamente con SQL Server. Y si utilizamos la clase OleDbConnection debemos especificar el proveedor OLEDB que se va a utilizar para establecer la conexin, una excepcin es el proveedor OLEDB para ODBC (MSDASQL), que no puede ser utilizado, ya que el proveedor OLEDB de .NET no soporta el proveedor de ODBC, en este caso deberemos realizar la conexin utilizando el proveedor adecuado al almacn de datos. Los proveedores OLEDB que son compatibles con ADO .NET son: SQLOLEDB: Microsoft OLE DB Provider for SQL Server. MSDAORA: Microsoft OLE DB Provider for Oracle. Microsoft.Jet.OLEDB.4.0: OLE DB Provider for Microsoft Jet.

La sintaxis utilizada para indicar la cadena de conexin, con las particularidades propias de cada proveedor, veremos que es muy similar a la utilizada en ADO clsico. El Cdigo fuente 559 muestra un ejemplo de conexin con un servidor SQL Server 2000, y su posterior desconexin, utilizando un objeto SqlConnection. Debemos importar el espacio de nombres Data.SqlClient para poder utilizar el objeto. Este cdigo lo podemos asociar a la pulsacin de un botn en un formulario.

Imports System.Data.SqlClient '.... Try ' crear el objeto de conexin Dim oConexion As New SqlConnection() ' pasar la cadena de conexin oConexion.ConnectionString = "server=(local);" & _

"database=Xnorthwind;uid=sa;pwd=;" ' abrir conexin oConexion.Open() MessageBox.Show("Conectado") ' cerrar conexin oConexion.Close() MessageBox.Show("Desconectado") Catch oExcep As SqlException ' si se produce algn error, ' lo capturamos mediante el objeto ' de excepciones particular para ' el proveedor de SQL Server MessageBox.Show("Error al conectar con datos" & _ ControlChars.CrLf & _ oExcep.Message & ControlChars.CrLf & _ oExcep.Server) End Try Cdigo fuente 559

El Cdigo fuente 560 muestra la misma operacin pero usando el objeto de conexin para el proveedor de OLEDB. Observe el lector las diferencias en las cadenas de conexin y el objeto de excepcin con respecto al anterior ejemplo, as como el espacio de nombres a importar.

Imports System.Data.OleDb '.... Try ' crear el objeto de conexin Dim oConexion As New OleDbConnection() oConexion.ConnectionString = "Provider=SQLOLEDB;" & _ "Server=(local);Database=Northwind;uid=sa;pwd=;" ' abrir conexin oConexion.Open() MessageBox.Show("Conectado") ' cerrar conexin oConexion.Close() MessageBox.Show("Desconectado") Catch oExcep As OleDbException ' si se produce algn error, ' lo capturamos mediante el objeto ' de excepciones particular para ' el proveedor de OLEDB MessageBox.Show("Error al conectar con datos" & _ ControlChars.CrLf & _ oExcep.Message & ControlChars.CrLf & _ oExcep.Source()) End Try Cdigo fuente 560

Las clases Command


Establecida una conexin con un almacn de datos, la siguiente operacin lgica consiste en enviarle sentencias para realizar los distintos tipos de operaciones que habitualmente realizamos con los datos. Las clases Command de ADO .NET sern las usaremos para realizar tales operaciones. SqlCommand y OleDbCommand, son muy similares al objeto Command existente en ADO. El objeto Command nos va a permitir ejecutar una sentencia SQL o un procedimiento almacenado sobre la fuente de datos a la que estamos accediendo. A travs de un objeto Command tambin podremos obtener un conjunto de resultados del almacn de datos. En este caso, los resultados se pasarn a otros objetos de ADO .NET, como DataReader o DataAdapter; estos dos objetos los comentaremos ms adelante. Un objeto Command lo vamos a crear a partir de una conexin ya existente, y va a contener una sentencia SQL para ejecutar sobre la conexin establecida con el origen de datos. Entre las propiedades que ofrecen los objetos SqlCommand y OleDbCommand, caben destacar las siguientes. CommandText. Contiene una cadena de texto que va a indicar la sentencia SQL o procedimiento almacenado que se va a ejecutar sobre el origen de los datos. CommandTimeout. Tiempo de espera en segundos que se va a aplicar a la ejecucin de un objeto Command. Su valor por defecto es de 30 segundos. CommandType. Indica el tipo de comando que se va a ejecutar contra el almacn de datos, es decir, indica como se debe interpretar el valor de la propiedad CommadText. Puede tener los siguientes valores: StoredProcedure, para indicar que se trata de un procedimiento almacenado; TableDirect se trata de obtener una tabla por su nombre (nicamente aplicable al objeto OleDbCommand); y Text que indica que es una sentencia SQL. EL valor por defecto es Text. Connection. Devuelve el objeto SqlConnection o OleDbConnection utilizado para ejecutar el objeto Command correspondiente. Parameters. Coleccin de parmetros que se pueden utilizar para ejecutar el objeto Command, esta coleccin se utiliza cuando deseamos ejecutar sentencias SQL que hacen uso de parmetros, esta propiedad devuelve un objeto de la clase SqlParameterCollection o un objeto de la clase OleDbParameterCollection. Estas colecciones contendrn objetos de la clase SqlParamter y OleDbParameter, respectivamente, para representar a cada uno de los parmetros utilizados. Estos parmetros tambin son utilizados para ejecutar procedimientos almacenados.

Una vez vistas algunas de las propiedades de las clases SqlCommand y OleDbCommand, vamos a pasar a comentar brevemente los principales mtodos de estas clases. CreateParameter. Crea un parmetro para el que despus podremos definir una serie de caractersticas especficas como pueden ser el tipo de dato, su valor, tamao, etc. Devolver un objeto de la clase SqlParameter u OleDbParameter. ExecuteNonQuery. Ejecuta la sentencia SQL definida en la propiedad ComandText contra la conexin definida en la propiedad Connection. La sentencia a ejecutar debe ser de un tipo que no devuelva un conjunto de registros, por ejemplo Update, Delete o Insert. Este mtodo

devuelve un entero indicando el nmero de filas que se han visto afectadas por la ejecucin del objeto Command. ExecuteReader. Ejecuta la sentencia SQL definida en la propiedad ComandText contra la conexin definida en la propiedad Connection. En este caso, la sentencia s devolver un conjunto de registros. El resultado de la ejecucin de este ser un objeto de la clase SqlDataReader/OleDbDataReader, que nos va a permitir leer y recorrer los resultados devueltos por la ejecucin del objeto Command correspondiente. ExecuteScalar. Este mtodo se utiliza cuando deseamos obtener la primera columna de la primera fila del conjunto de registros, el resto de datos no se tendrn en cuenta. La utilizacin de este mtodo tiene sentido cuando estamos ejecutando una sentencia SQL del tipo Select Count(*). Este mtodo devuelve un objeto de la clase genrica Object. Prepare. Este mtodo construye una versin compilada del objeto Command dentro del almacn de datos.

A continuacin mostraremos algunos ejemplos de uso de objetos Command. El Cdigo fuente 561 ilustra la insercin de un registro utilizando un objeto SqlCommand. En primer lugar utilizamos un constructor de la clase, que recibe como parmetro la sentencia a ejecutar y la conexin. Como vamos a ejecutar una sentencia que no produce un conjunto de resultados, emplearemos el mtodo ExecuteNonQuery( ). Observe tambin el lector en este ejemplo, que la conexin slo permanece abierta en el momento de ejecutar el comando; esta es la tcnica recomendable que debemos utilizar para todas las operaciones con datos: mantener abierta la conexin el menor tiempo posible.

' crear conexin Dim oConexion As New SqlConnection() oConexion.ConnectionString = "Server=(local);" & _ "Database=Gestion;uid=sa;pwd=;" ' crear sentencia SQL Dim sSQL As String sSQL = "INSERT INTO Clientes (IDCliente,Nombre,FIngreso) " & _ "VALUES(10,'Alfredo','18/7/2002')" ' crear comando Dim oComando As New SqlCommand(sSQL, oConexion) Dim iResultado As Integer oConexion.Open() ' abrir conexin iResultado = oComando.ExecuteNonQuery() ' ejecutar comando oConexion.Close() ' cerrar conexin MessageBox.Show("Registros aadidos:" & iResultado) Cdigo fuente 561

En el Cdigo fuente 562 realizamos tambin la insercin con un SqlCommand, pero utilizando en este caso parmetros. En la cadena que tiene la sentencia SQL indicaremos los parmetros con el formato @NombreParmetro. Para crear cada uno de los parmetros utilizaremos la clase SqlParameter, mientras que para aadir los parmetros usaremos la coleccin Parmeters del objeto SqlCommand y su mtodo Add( ).

Respecto a la creacin de los parmetros, podemos observar que es muy flexible, ya que como vemos en este ejemplo, cada uno de ellos se crea de un modo distinto, especificando el nombre, tipo de dato y valor.

' crear conexin Dim oConexion As New SqlConnection() oConexion.ConnectionString = "Server=(local);" & _ "Database=Gestion;uid=sa;pwd=;" ' crear sentencia SQL para insertar un registro con ' parmetros; indicamos el nombre del parmetro con ' @NombreParmetro Dim sSQL As String sSQL = "INSERT INTO Clientes (IDCliente,Nombre,FIngreso) " & _ "VALUES(@CodCli,@Nombre,@Fecha)" ' crear comando Dim oComando As New SqlCommand(sSQL, oConexion) ' aadir parmetros al comando: ' parmetro primer campo oComando.Parameters.Add(New SqlParameter("@CodCli", _ SqlDbType.Int)) oComando.Parameters("@CodCli").Value = 25 ' parmetro segundo campo oComando.Parameters.Add(New SqlParameter("@Nombre", "Raquel")) ' parmetro tercer campo Dim oParametro As New SqlParameter() oParametro.ParameterName = "@Fecha" oParametro.SqlDbType = SqlDbType.DateTime oParametro.Value = "25/10/2002" oComando.Parameters.Add(oParametro) Dim iResultado As Integer oConexion.Open() ' abrir conexin iResultado = oComando.ExecuteNonQuery() ' ejecutar comando oConexion.Close() ' cerrar conexin MessageBox.Show("Registros aadidos:" & iResultado) Cdigo fuente 562

Si empleamos un objeto OleDbCommand, la sintaxis de la sentencia SQL cambia, ya que los parmetros deberemos indicarlos como hacamos en ADO clsico, utilizando el carcter ?. Veamos un ejemplo en el Cdigo fuente 563.

' crear el objeto de conexin Dim oConexion As New OleDbConnection() oConexion.ConnectionString = "Provider=SQLOLEDB;" & _ "Server=(local);Database=Gestion;uid=sa;pwd=;" ' crear sentencia SQL para modificar un registro con ' parmetros; indicamos el parmetro con ? Dim sSQL As String sSQL = "UPDATE Clientes SET Nombre = ? " & _ "WHERE IDCliente = 2"

' crear comando Dim oComando As New OleDbCommand(sSQL, oConexion) oComando.Parameters.Add(New OleDbParameter("NombreCli", _ OleDbType.VarChar, 50)) oComando.Parameters("NombreCli").Value = "David" Dim iResultado As Integer oConexion.Open() ' abrir conexin iResultado = oComando.ExecuteNonQuery() ' ejecutar comando oConexion.Close() ' cerrar conexin MessageBox.Show("Registros modificados:" & iResultado) Cdigo fuente 563

En el caso de que necesitemos ejecutar un procedimiento almacenado, debemos indicarlo mediante las propiedades CommandType y CommandText del objeto Command que estemos utilizando. En la primera establecemos el tipo de comando (procedimiento almacenado) seleccionando el valor de la enumeracin asociada a la propiedad; y en la segunda asignamos una cadena con el nombre del procedimiento almacenado. El Cdigo fuente 564 muestra un ejemplo, en el que podemos comprobar que hemos utilizado un constructor de SqlCommand sin parmetros, por lo que el objeto Connection lo asignamos despus mediante la propiedad Connection

' crear conexin Dim oConexion As New SqlConnection() oConexion.ConnectionString = "Server=(local);" & _ "Database=Gestion;uid=sa;pwd=;" ' crear comando para ejecutar procedimiento almacenado ' que borra un registro Dim oComando As New SqlCommand() oComando.Connection = oConexion oComando.CommandType = CommandType.StoredProcedure oComando.CommandText = "BorraCli" ' aadir parmetro al comando oComando.Parameters.Add(New SqlParameter("@IDCliente", _ SqlDbType.Int)) oComando.Parameters("@IDCliente").Value = 25 Dim iResultado As Integer oConexion.Open() ' abrir conexin iResultado = oComando.ExecuteNonQuery() ' ejecutar comando oConexion.Close() ' cerrar conexin MessageBox.Show("Registros borrados:" & iResultado) Cdigo fuente 564

Para obtener el resultado de una funcin del lenguaje SQL, por ejemplo Count( ), emplearemos el mtodo ExecuteScalar( ) del objeto Command. En el Cdigo fuente 565, la ejecucin de este mtodo nos devuelve el nmero de filas de una tabla de la base de datos, que mostramos en un mensaje.

' crear conexin Dim oConexion As New SqlConnection()

oConexion.ConnectionString = "Server=(local);" & _ "Database=Gestion;uid=sa;pwd=;" ' crear comando escalar Dim sSQL As String sSQL = "SELECT COUNT(*) FROM Clientes" ' crear comando Dim oComando As New SqlCommand(sSQL, oConexion) Dim iResultado As Integer oConexion.Open() ' abrir conexin iResultado = oComando.ExecuteScalar() ' ejecutar comando oConexion.Close() ' cerrar conexin MessageBox.Show("Nmero de registros de clientes:" & iResultado) Cdigo fuente 565

Las clases DataReader


Un objeto DataReader permite la navegacin hacia delante y de slo lectura, de los registros devueltos por una consulta. Es lo ms parecido al objeto Recordset de ADO de tipo read only/forward only. A diferencia del resto de objetos, que siguen un esquema desconectado de manipulacin de datos, los DataReader permanecen conectados durante todo el tiempo que realizan el recorrido por los registros que contienen. Las clases que implementan este tipo de objeto son SqlDataReader y OleDbDataReader. Para obtener un DataReader, ejecutaremos el mtodo ExecuteReader( ) de un objeto Command basado en una consulta SQL o procedimiento almacenado. A continuacin vamos a pasar a describir las principales propiedades de las clases SqlDataReader y OleDbDataReader. FieldCount. Devuelve el nmero de columnas (campos) presentes en el fila (registro) actual. IsClosed. Devolver los valores True o False, para indicar si el objeto DataReader est cerrado o no. Item. Devuelve en formato nativo, el valor de la columna cuyo nombre le indicamos como ndice en forma de cadena de texto.

Una vez vistas las propiedades, vamos a comentar los mtodos ms destacables. Close( ). Cierra el objeto DataReader liberando los recursos correspondientes. GetXXX( ). El objeto DataReader presenta un conjunto de mtodos que nos van a permitir obtener los valores de las columnas contenidas en el mismo en forma de un tipo de datos determinado, segn el mtodo GetXXX empleado. Existen diversos mtodos GetXXX atendiendo al tipo de datos de la columna, algunos ejemplos son GetBoolean(), GetInt32(), GetString(), GetChar(), etc. Como parmetro a este mtodo le debemos indicar el nmero de orden de la columna que deseamos recuperar. NextResult( ). Desplaza el puntero actual al siguiente conjunto de registros, cuando la sentencia es un procedimiento almacenado de SQL o una sentencia SQL que devuelve ms de

un conjunto de registros, no debemos confundir este mtodo con el mtodo MoveNext() de ADO, ya que en este caso no nos movemos al siguiente registro, sino al siguiente conjunto de registros. Read( ). Desplaza el cursor actual al siguiente registro permitiendo obtener los valores del mismo a travs del objeto DataReader. Este mtodo devolver True si existen ms registros dentro del objeto DataReader, False si hemos llegado al final del conjunto de registros. La posicin por defecto del objeto DataReader en el momento inicial es antes del primer registro, por lo tanto para recorrer un objeto DataReader debemos comenzar con una llamada al mtodo Read(), y as situarnos en el primer registro.

El proyecto PruDataReader (hacer clic aqu para acceder al ejemplo), contiene un formulario con algunos controles, que muestran el uso de objetos DataReader. El botn Empleados crea a partir de un comando, un objeto DataReader que recorremos para llenar un ListBox con los valores de una de las columnas de la tabla que internamente contiene el DataReader. Veamos este caso en el Cdigo fuente 566.

Private Sub btnEmpleados_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEmpleados.Click ' crear conexion Dim oConexion As New SqlConnection() oConexion.ConnectionString = "Server=(local);" & _ "Database=Northwind;uid=sa;pwd=;" ' crear comando Dim oComando As New SqlCommand("SELECT * FROM Employees", _ oConexion) ' crear DataReader Dim oDataReader As SqlDataReader oConexion.Open() oDataReader = oComando.ExecuteReader() ' obtener DataReader ' recorrer filas While oDataReader.Read() Me.lstEmpleados.Items.Add(oDataReader("LastName")) End While oDataReader.Close() oConexion.Close() End Sub Cdigo fuente 566

Como tambin hemos indicado anteriormente, un objeto Command puede estar basado en mltiples sentencias SQL, separadas por el carcter de punto y coma ( ; ), que se ejecuten en lote. Al crear un DataReader desde un comando de este tipo, podemos recorrer el conjunto de consultas mediante el mtodo NextResult( ) del DataReader. Un ejemplo de este tipo lo tenemos al pulsar el botn Clientes/Productos del formulario, cuyo fuente vemos a continuacin en el Cdigo fuente 567. Observe en este caso que conectamos a travs de OLE DB, por lo que empleamos los objetos ADO .NET de esta categora.

Private Sub btnCliProd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCliProd.Click ' crear conexion Dim oConexion As New OleDbConnection() oConexion.ConnectionString = "Provider=SQLOLEDB;" & _ "Server=(local);Database=Northwind;uid=sa;pwd =;" ' crear comando compuesto por varias consultas Dim oComando As New OleDbCommand("SELECT * FROM Customers; SELECT * FROM Products", oConexion) Dim oDataReader As OleDbDataReader oConexion.Open() oDataReader = oComando.ExecuteReader() ' obtener DataReader ' recorrer filas de la primera consulta While oDataReader.Read() Me.lstClientes.Items.Add(oDataReader("CompanyNam e")) End While ' pasar a la siguiente consulta y recorrer ' las filas oDataReader.NextResu lt() While oDataReader.Read() Me.lstProductos.Items.Add(oDataReader("ProductNam e")) End While oDataReader.Close() oConexion.Close() End Sub Cdigo fuente 567

La Figura 342 muestra este formulario despus de haber rellenado los controles ListBox usando objetos DataReader.

Figura 342. ListBox llenados con objetos DataReader.

También podría gustarte