Continuando con el curso Inicio en Visual C#.
El acceso a fuentes de datos es algo indispensable en cualquier lenguaje o plataforma de desarrollo. La parte de la BCL que se especializa en el acceso a datos se denomina de forma genérica como ADO.NET.
Si usted ha programado con Visual Basic 6.0 o con ASP, ha empleado en su código con total seguridad la interfaz de acceso a datos conocida como ADO (ActiveX Data Objects), puede que combinado con ODBC (Open Database Connectivity). Si además es usted de los programadores con solera y lleva unos cuantos años en esto es probable que haya usado RDO o incluso DAO, todos ellos métodos mucho más antiguos.
ADO.NET ofrece una funcionalidad completamente nueva, que tiene poco que ver con lo existente hasta la fecha en el mercado. Sin embargo, con el ánimo de retirar barreras a su aprendizaje, Microsoft denominó a su nuevo modelo de acceso a datos con un nombre similar y algunas de sus clases recuerdan a objetos de propósito análogo en el vetusto ADO.
ADO.NET es un modelo de acceso mucho más orientado al trabajo desconectado de las fuentes de datos de lo que nunca fue ADO. Si bien este último ofrecía la posibilidad de desconectar los Recordsets y ofrecía una forma de serialización de estos a través de las diferentes capas de una aplicación, el mecanismo no es ni de lejos tan potente como el que nos ofrece ADO.NET.
El objeto más importante a la hora de trabajar con el nuevo modelo de acceso a datos es el DataSet. Sin exagerar demasiado podríamos calificarlo casi como un motor de datos relacionales en memoria. Aunque hay quien lo asimila a los clásicos Recordsets su funcionalidad va mucho más allá como se verá en el correspondiente módulo.
Arquitectura de ADO.NET
El concepto más importante que hay que tener claro sobre ADO.NET es su modo de funcionar, que se revela claramente al analizar su arquitectura:
Figura 1.3.- Arquitectura de ADO.NET
Existen dos capas fundamentales dentro de su arquitectura: la capa conectada y la desconectada.
Capa conectada
La primera de ellas contiene objetos especializados en la conexión con los orígenes de datos. Así, la clase genérica Connection se utiliza para establecer conexiones a los orígenes de datos. La clase Command se encarga de enviar comandos de toda índole al origen de datos. Por fin la clase DataReader está especializada en leer los resultados de los comandos mientras se permanece conectado al origen de datos.
La clase DataAdapter hace uso de las tres anteriores para actuar de puente entre la capa conectada y la desconectada.
Estas clases son abstractas, es decir, no tienen una implementación real de la que se pueda hacer uso directamente. Es en este punto en donde entran en juego los proveedores de datos. Cada origen de datos tiene un modo especial de comunicarse con los programas que los utilizan, además de otras particularidades que se deben contemplar. Un proveedor de datos de ADO.NET es una implementación concreta de las clases conectadas abstractas que hemos visto, que hereda de éstas y que tiene en cuenta ya todas las particularidades del origen de datos en cuestión.
Así, por ejemplo, las clases específicas para acceder a SQL Server se llaman SqlConnection, SqlCommand, SqlDataReader y SqlDataAdapter y se encuentran bajo el espacio de nombres System.Data.SqlClient. Es decir, al contrario que en ADO clásico no hay una única clase Connection o Command que se use en cada caso, si no que existen clases especializadas para conectarse y recuperar información de cada tipo de origen de datos.
Nota:
El hecho de utilizar clases concretas para acceso a las fuentes de datos no significa que no sea posible escribir código independiente del origen de datos. Todo lo contrario. La plataforma .NET ofrece grandes facilidades de escritura de código genérico basadas en el uso de herencia e implementación de interfaces. De hecho la versión 2.0 de .NET ofrece grandes novedades específicamente en este ámbito.
Existen proveedores nativos, que son los que se comunican directamente con el origen de datos (por ejemplo el de SQL Server o el de Oracle), y proveedores "puente", que se utilizan para acceder a través de ODBC u OLEDB cuando no existe un proveedor nativo para un determinado origen de datos.
Nota:
Estos proveedores puente, si bien muy útiles en determinadas circunstancias, ofrecen un rendimiento menor debido a la capa intermedia que están utilizando (ODBC u OLEDB). Un programador novel puede sentir la tentación de utilizar siempre el proveedor puente para OLEDB y así escribir código compatible con diversos gestores de datos de forma muy sencilla. Se trata de un error y siempre que sea posible es mejor utilizar un proveedor nativo.
Capa desconectada
Una vez que ya se han recuperado los datos desde cualquier origen de datos que requiera una conexión ésta ya no es necesaria. Sin embargo sigue siendo necesario trabajar con los datos obtenidos de una manera flexible. Es aquí cuando la capa de datos desconectada entra en juego. Además, en muchas ocasiones es necesario tratar con datos que no han sido obtenidos desde un origen de datos relacional con el que se requiera una conexión. A veces únicamente necesitamos un almacén de datos temporal pero que ofrezca características avanzadas de gestión y acceso a la información.
Por otra parte las conexiones con las bases de datos son uno de los recursos más escasos con los que contamos al desarrollar. Su mala utilización es la causa más frecuente de cuellos de botella en las aplicaciones y de que éstas no escalen como es debido. Esta afirmación es especialmente importante en las aplicaciones Web en las que se pueden recibir muchas solicitudes simultáneas de cualquier parte del mundo.
Finalmente otro motivo por el que es importante el uso de los datos desconectado de su origen es la transferencia de información entre capas de una aplicación. Éstas pueden encontrarse distribuidas por diferentes equipos, e incluso en diferentes lugares del mundo gracias a Internet. Por ello es necesario disponer de algún modo genérico y eficiente de poder transportar los datos entre diferentes lugares, utilizarlos en cualquiera de ellos y posteriormente tener la capacidad de conciliar los cambios realizados sobre ellos con el origen de datos del que proceden.
Todo esto y mucho más es lo que nos otorga el uso de los objetos DataSet. Es obvio que no se trata de tareas triviales, pero los objetos DataSet están pensados y diseñados con estos objetivos en mente. Como podremos comprobar más adelante en este curso es bastante sencillo conseguir estas funcionalidades tan avanzadas y algunas otras simplemente usando de manera adecuada este tipo de objetos.
Nota:
Otra interesante característica de los DataSet es que permiten gestionar simultáneamente diversas tablas (relaciones) de datos, cada una de un origen diferente si es necesario, teniendo en cuenta las restricciones y las relaciones existentes entre ellas.
Los DataSet, como cualquier otra clase no sellada de .NET, se pueden extender mediante herencia. Ello facilita una técnica avanzada que consiste en crear tipos nuevos de DataSet especializados en la gestión de una información concreta (por ejemplo un conjunto de tablas relacionadas). Estas nuevas tipos clases se denominan genéricamente DataSet Tipados, y permiten el acceso mucho más cómodo a los datos que representan, verificando reglas de negocio, y validaciones de tipos de datos más estrictas.