Migrando a ADO.NET
Gerardo Díaz Ferrándiz
MCT, MCSD, MCDBA, MCSE
ADO.NET es la mas reciente tecnología de acceso a datos, muchos desarrolladores desean comenzar a diseñar aplicaciones utilizando esta nueva y potente librería, pero realmente, hasta donde quiere Microsoft llevar el concepto de "cliente desconectado"?, en este artículo abordaremos las mejores formas de obtener el máximo rendimiento de las nuevas funcionalidades que ofrece ADO.NET
ADO.NET siempre fue uno de los componentes más notables, al menos a mi parecer, dentro de la nueva generación de aplicaciones .NET. Es decir, es bastante sencillo entender la evolución natural de una herramienta de desarrollo de una versión a otra, por ejemplo una nueva versión de Visual Basic o de Power Builder, sin embargo las implicancias que tiene un nuevo "engine" de acceso a datos son enormes, sobre todo considerando que el 80% de las aplicaciones escritas acceden a alguna fuente de datos. Entonces, ¿era realmente necesario para Microsoft re-escribir un "engine" de acceso a datos, si aparentemente los programadores teníamos todo lo necesario para escribir aplicaciones?. Al menos eso creía.
Antes que nada, ADO.NET ahora es parte del .NET Framework, esto quiere decir que es, de alguna manera, parte del Sistema Operativo y no más un redistribuible de 4 o 5 MB que se necesita alojar en la PC del cliente o junto al instalador de una aplicación. Este hecho representa una enorme ventaja debido a que uno, cómo desarrollador, puede enfocarse en utilizar el acceso a datos y no tanto en cómo se desplegará a los clientes la librería. Toda la funcionalidad de ADO.NET esta constituida dentro de estas clases del .NET Framework:
Una ventaja que ADO.NET brinda al ser parte del .NET Framework es que todos los lenguajes compatibles con .NET utilizan las mismas clases para acceder y manipular datos, únicamente es la sintaxis la que difiere en cada lenguaje de desarrollo que se utiliza. Por ejemplo, VB, C# o cualquier lenguaje compatible con NET, abrirá una conexión a una base de datos MS SQL Server 2000 utilizando exactamente la misma librería, System.SqlClient.SqlConnection en este caso.
Con Everett, la siguiente versión de Visual Studio NET, así como con las versiones posteriores vendrán inminentes actualizaciones al .NET Framework, v1.1, v.2.0, etc. La idea, básicamente, es crecer a partir de las clases arriba mencionadas, digamos que solo bastará con actualizar la PC del cliente a la versión del .NET Framework correspondiente, para asumir que todos los componentes incluyendo ADO.NET poseen la versión correcta.
Modelo ADO.NET
ADO.NET es bastante más amigable con MS SQL Server que antes, si bien en ADO 2.x utilizando proveedores nativos se podía establecer una conexión a una base de datos omitiendo ciertas capas de conversión como ODBC, era necesario especificar esta información con el atributo PROVIDER=SQLOLEDB en la propiedad connectionstring del objeto connection. Esto ya no es necesario en ADO.NET, basta solo con utilizar la librería System.Data.SqlClient.SqlConnection, escrita específicamente para MSSQLServer 7.x o posterior, para obtener mayores ventajas que simplemente omitiendo capas de conversión. ADO.NET es capaz de utilizar internamente TDS (Tabular Data Stream), el mismo mecanismo de comunicación que SQL Server 7.x y posterior utiliza internamente, ahorrando tiempo y recursos evitando realizar conversiones de ADO a OLEDB y de OLEDB a ODBC y de ODBC a la fuente de datos, la cual utiliza TDS finalmente. Este es un gran avance en acceso a datos.
Sin embargo, para los que no tengan la suerte de contar con un servidor de base de datos MSSQLServer 7.0 o posterior, ADO.NET utiliza su clase System.Data.Oledb. Gracias a esta biblioteca, Microsoft soporta acceso a diferentes fuentes bajo el mismo modelo de acceso a datos. Si bien se mantiene separado los objetos SqlClient y OleDb, ambos implementan clases y objetos similares entre ellos lo que hace muy sencillo interactuar con ellos.
Dentro de estas clases se encuentran objetos muy familiares como Connection o Command los cuales básicamente se comportan en una forma muy similar que en la versión previa de ADO. Los cambios sobre todo obedecen a funcionalidad, rendimiento e interoperabilidad con una forma estándar de representación de datos a través de XML.
Conectado o Desconectado
Microsoft ha puesto en su lista de prioridades para ADO.NET el que cada vez los desarrolladores puedan escribir aplicaciones más y más escalables, y para hacerlo debemos reducir al máximo el numero de "conexiones abiertas" en la base de datos. No es ningún secreto que en ADO el mejor rendimiento se obtenía manteniendo una conexión abierta a la fuente de datos, sin embargo, en ADO.NET, gracias a los DataSets es posible tomar una parte de los datos y mantenerlos en memoria en forma relacional, tal cual son almacenados. Esto permite brindarle datos a la aplicación cliente sin sacrificar el rendimiento al mantener conexiones abiertas a la base de datos.
Los DataSets son un concepto realmente revolucionario y sin precedentes. Son, básicamente, representaciones en memoria de algo más que una simple tabla, es posible verlo como una porción de base de datos en la memoria de la PC del cliente, el cual puede contener tablas, relaciones, e incluso hasta contraints (primary keys, foreign keys, uniques). La idea detrás de esto es que la aplicación cuente con todos los datos necesarios para poder trabajar, y por ninguna razón requiera conectarse a la base de datos, salvo para cargar o actualizar los cambios generados en el DataSet. Temporalmente los datos pueden ser almacenados a disco por ejemplo directamente a un archivo XML, bastará con utilizar el método WriteXml y WriteXmlSchema del objeto DataSet:
wDataset.WriteXmlSchema "c:\dataet_estructura.xsd"
wDataset.WriteXml "c:\dataset_datos.xml"
Con esto se esta volcando toda la estructura básicamente en 2 pasos, primero la estructura, es decir, definición de tablas, columnas, tipos de datos, constraints, relaciones, etc y en la segunda instrucción es el vaciado de los datos.
Luego si mas adelante la aplicación debe de recuperar estos datos únicamente tendrá que llamarlos utilizando:
wDataset.ReadXmlSchema "c:\dataet_estructura.xsd"
wDataset.ReadXml "c:\dataset_datos.xml"
Imaginemos, al inicio de una aplicación desconectada abrir este par de archivos, luego al momento de cerrar, grabar el contenido del DataSet a disco, ahora nos preguntamos, para que se necesita la base de datos?. Básicamente el DataSet puede volcar todos los cambios dentro de si a la base de datos nuevamente.
Veamos esto un poco más a fondo, nosotros debemos definir los datos que estarán dentro del DataSet, es decir, si se quiere construir un cliente desconectado se tiene que entender, que este cliente interactuará únicamente con los datos contenidos dentro del DataSet, por lo tanto, se tiene que seleccionar cuidadosamente qué información estará dentro de dicho DataSet. Los candidatos favoritos son los maestros, es decir, maestro de productos, maestro de clientes, maestro de locales, etc. Con mayor cuidado se tiene que considerar a las tablas centrales y dependerá mucho del tipo de aplicación que utilice para solo incluir porciones de esta información.
No es necesario obtener toda la tabla de ventas (que posiblemente contenga 200 mil registros) al DataSet, si podemos anticipar que el usuario puede modificar una parte de estos. Básicamente este el concepto detrás de los DataSets: incluir únicamente la información necesaria que se espera sea trabajada y modificada.
Contrariamente a los que tal vez se haya escuchado, no todo es "desconectado" dentro del mundo de ADO.NET. Microsoft sabe que un gran volumen de aplicaciones por sus requerimientos y por la naturaleza del negocio requieren una arquitectura conectada, mas aún, en aplicaciones que cuentan con un alto volumen de actualizaciones de datos y necesitan contar con la data fresca al instante, los DataSets no son la mejor opción, siendo el modelo "conectado" el que mejor se adapta a este escenario. Bajo este modelo, estamos en algo muy similar a los Recordsets que conocíamos en la versión 2.X de ADO. Si mal no se recuerda, el objeto Recordset que conocíamos incluía muchas características que ocasionalmente usábamos, si bien éste era un súper repositorio, nos permitía ordenar, filtrar, buscar datos dentro del mismo, cuando tal vez lo único que quería era recibir los datos que la base de datos nos enviaba para poder poblar un control o llenar una lista.
El objeto bandera del modelo conectado en ADO.NET se llama DataReader, cada clase implementa uno propio, SQLDataReader o OledbDataReader, ambos básicamente hacen lo mismo: proporcionar un objeto simple, rápido y liviano donde poder recibir los datos que envía la BD y procesarlos, un registro a la vez, similar a un cursor Forwardonly en ADO. Este objeto no puede existir por sí solo, debe ser creado a partir de un objeto Command utilizando su método ExecuteReader (ver linea 1 y 2), luego de obtenerlo, se puede recorrer el resultado hacia abajo un registro a la vez. El método Read del DataReader realiza dos funciones, primero devuelve un valor booleano indicando si existen más datos dentro del objeto y segundo, realiza un MoveNext implícito para poder moverse al siguiente registro.
1 Dim miReader As OleDbDataReader = Nothing
2 miReader = miCommando.ExecuteReader()
4 While miReader.Read
5 MsgBox(miReader.GetString(1))
6 End While
Entonces se tienen dos escenarios, ambos tienen ventajas y desventajas. Si bien el escenario "conectado" simplifica muchas tareas como el extraer directamente los datos y manipularlos rápidamente con el objeto DataReader, también limita la escalabilidad porque es mayor el numero de veces que se realizaran consultas a la base de datos, siendo necesario incluso el recurrir a comandos adicionales para enviar los cambios realizados a la información, ya sea vía Procedimientos Almacenados o sentencias sql. En el lado contrario, el modelo conectado trabaja tranquilamente con una porción desconectada de los datos, gracias a esto, se puede crear vistas, navegar dentro del DataSet, vincularlo a cualquier control y otras funcionalidades, el problema radica generalmente al momento de vaciar los datos a la fuente de datos, debido a que estos pudieron ser alterados, modificados o incluso borrados por otros usuarios mientras se trabaja en forma desconectada.
Los DataSets también involucran un trabajo más minucioso de diseño de base de datos, debido a justamente a la naturaleza desconectada con los que los datos serán extraídos y actualizados posteriormente.
Aplicaciones Distribuidas
Microsoft ha visto evolucionar en los últimos años las aplicaciones distribuidas. Cada vez son más los negocios que necesitan desplazar información entre componentes dentro y fuera de la empresa. ADO.NET ofrece una ventaja tremenda respecto a su antecesor, ya que es capaz de representar repositorios como DataSet en forma de XML, como vimos en un ejemplo anterior.
Hemos visto en el pasado aplicaciones distribuidas donde los componentes COM se comunican entre las capas enviando y devolviendo Recordsets conectados. Esto causaba una sobrecarga tremenda debido a lo complejo y pesado que es en si el objeto Recordset, sin mencionar que existe un enlace permanente entre el cliente y el servidor que proporciona dicho objeto al acceder a cualquier propiedad o método del recordset del lado del cliente. Los usuarios pagaban el precio del rendimiento, por la funcionalidad y facilidad con la que pueden manipular Recordsets conectados dentro de los componentes.
Una solución a esto fue el utilizar recordsets desconectados, los cuales se comportan mejor que los anteriores en lo referido a performance, pero aun requieren el marshalling que COM impone para que estos objetos sean transportados entre capas de una aplicación. La ventaja de los recordsets desconectados radicaba en que realmente lo que se devolvía al cliente era únicamente era un rowset y metadata (descripción de las tablas, columnas, etc) en vez del objeto recordset en si, con esto se podía reconstruir el objeto recordset del lado del cliente obteniendo un objeto nuevo y en cierta forma independiente, esto constituye una excepción solo en el caso de los recordsets desconectados.
ADO.NET a través de los Datasets provee repositorios inteligentes de datos que pueden comportarse mucho mejor que los tradicionales Recordsets o arreglos. No producen sobrecargas debido a que lo que transmiten es texto XML y no representaciones de objetos los cuales son más complejos y pesados.
El trasmitir estos Datasets es tan simple como que nuestras funciones continúen devolviendo valores string, pero estos están estructurados en XML.
Public Function GetClientes() as String
Dim wDataSet as new DataSet
……
….. Código necesario para llenar el dataset
…..
Return wDataset.GetXml
End Function
Ahora si este método esta definido dentro de un web service, GetXML transformará al Dataset en una documento XML el cual será devuelto por la función y transmitido por ejemplo si se usa web services, vía http hasta el extremo del cliente donde podría reconstruirse, sin causar la sobrecarga como el caso del objeto recordset.
Conclusiones
En este artículo se ha tratado de dar una visión amplia de ADO.NET, así como las ventajas frente a su antecesor. Se ha presentado el soporte que presenta tanto para escenarios conectados como desconectados. Definitivamente el alcance de este nuevo engine de acceso a datos va más allá de las expectativas de muchos desarrolladores e implica no solo el tratar de adaptarlo a una aplicación existente, sino compromete el invertir mayor tiempo en el análisis y desarrollo de un soporte de base de datos relacional adecuado y pensado en una aplicación desconectada.


LinkBack URL
About LinkBacks
Una ventaja que ADO.NET brinda al ser parte del .NET Framework es que todos los lenguajes compatibles con .NET utilizan las mismas clases para acceder y manipular datos, únicamente es la sintaxis la que difiere en cada lenguaje de desarrollo que se utiliza. Por ejemplo, VB, C# o cualquier lenguaje compatible con NET, abrirá una conexión a una base de datos MS SQL Server 2000 utilizando exactamente la misma librería, System.SqlClient.SqlConnection en este caso.
Sin embargo, para los que no tengan la suerte de contar con un servidor de base de datos MSSQLServer 7.0 o posterior, ADO.NET utiliza su clase System.Data.Oledb. Gracias a esta biblioteca, Microsoft soporta acceso a diferentes fuentes bajo el mismo modelo de acceso a datos. Si bien se mantiene separado los objetos SqlClient y OleDb, ambos implementan clases y objetos similares entre ellos lo que hace muy sencillo interactuar con ellos.
Dentro de estas clases se encuentran objetos muy familiares como Connection o Command los cuales básicamente se comportan en una forma muy similar que en la versión previa de ADO. Los cambios sobre todo obedecen a funcionalidad, rendimiento e interoperabilidad con una forma estándar de representación de datos a través de XML.
No es necesario obtener toda la tabla de ventas (que posiblemente contenga 200 mil registros) al DataSet, si podemos anticipar que el usuario puede modificar una parte de estos. Básicamente este el concepto detrás de los DataSets: incluir únicamente la información necesaria que se espera sea trabajada y modificada.
Aplicaciones Distribuidas
