La Evolución de las APIs de Acceso a Datos de Microsoft - Parte II
La semana pasada publiqué la primera parte de un post acerca de la evolución de las APIs de Acceso a Datos de Microsoft. El mismo es una trascripción resumida de la excelente serie de artículos publicada por Mike Pizzo, Arquitecto en el equipo de Data Programmability de Microsoft. Este post es la segunda y última parte en la que se relata el aparecimiento de ADO.NET y los últimos avances en acceso a datos.
Acceso a Datos Desconectado: ADO.NET
Teniendo ya un framework común, coherente y administrado para escribir aplicaciones (.NET Framework), Microsoft se preguntó una vez más: "Cuál sería la mejor forma de acceder a datos?" Inicialmente se pensó en reutilizar la mayoría de la arquitectura ADO/OLE DB, pero el mundo ya no era el mismo.
Dada la creciente popularidad del Internet, la programación desconectada se estaba haciendo más importante en la industria y XML era ya una forma popular de trabajar con datos. ADO.NET enfrentó estos nuevos retos haciendo una separación explícita entre acceso a datos conectado (a través de "Proveedores de Datos" específicos) y acceso a datos desconectado (a través de un "DataSet" común manejado en memoria) con un mecanismo explícito y extensible conocido como "DataAdapter" para hacer un puente entre ambos.
Esta separación entre acceso a datos conectado y desconectado contrastó con ADO/OLE DB, el cual trataba de abstraer las diferencias en las funcionalidades de acceso remoto y orígenes de datos. Aún cuando el modelo de ADO de tener un RecordSet único que podría ser "forward-only" ó "scrollable" y que podría representar datos locales ó remotos, parecía una simplificación agradable, en la práctica las diferencias en funcionalidad, latencia, uso de memoria y los lugares donde podrían ocurrir errores hacían difícil esconder los detalles de dichas diversas implementaciones bajo una fachada común. Aún haciendo que las interfaces parezcan iguales, dichas diferencias afectaban fundamentalmente la forma en la que la aplicaciones se comportaban. Entonces, para construir aplicaciones confiables y que respondan en el momento apropiado, el acceso remoto necesitaba hacerse de forma asincrónica y de una forma tal que se eviten bloqueos, lo cual significaba conocer cuándo una operación era (potencialmente) remota.
Aún cuando se intentó preservar lo mayor posible del paradigma de programación ADO, el paso a ADO.NET fue dramático para la mayoría de los programadores. Inicialmente la pregunta "Qué pasó con mi ADO?" fue la primera reacción de los programadores, pero con el tiempo se dieron cuenta del poder que la separación explícita entre conectado y desconectado proveían, y con ello un sentimiento de "Nunca podría volver atrás".
Cada una de estas evoluciones fue impulsada por un cambio mayor en la plataforma; una interfaz de cliente para comunicarse con almacenes de datos relacionales; escenarios de scripting y RAD (rapid application development); COM/DCOM; un .NET Framework cohesivo. Y en cada caso se trató de proveer la API apropiada para la nueva plataforma mientras se mantenían conceptos de APIs previas y se consideraban las lecciones aprendidas y cambios en la industria.
El Modelo Conceptual: ADO.NET Entities y LINQ
ADO.NET Entities aprovecha la inversión realizada en ADO.NET agregándole la habilidad de escribir aplicaciones contra un esquema conceptual enriquecido llamado "Entity Data Model", en lugar de utilizar un esquema relacional de base de datos. El Entity Data Model (EDM) extiende el modelo de datos relacional con Entity-Relationships (ER) para modelar conceptos del mundo real como Herencia (autos y camiones son vehículos), Relaciones (los clientes tienen órdenes), y miembros complejos (calle, ciudad, región y código postal compuestos como una sola propiedad "dirección" de un cliente). Una gramática SQL extendida llamada "Entity SQL" permite consultar directamente el modelo conceptual, aprovechando herencias, accediendo a miembros complejos y navegando relaciones. En muchos casos, el utilizar el esquema conceptual y el lenguaje de queries elimina la necesidad de joins, uniones y subqueries complejos para hacer operaciones conceptualmente simples.
Estos esquemas conceptuales son expuestos y consultados a través de un "Entity Client", el cual es un Proveedor de datos ADO.NET que construye queries contra proveedores de almacenamiento específico usando "vistas" de lectura/escritura en el lado cliente. Toda la ejecución del query como tal se la realiza en el almacén (mas no en el cliente), y los resultados son ensamblados en resultados que pueden ser jerárquicos, polimórficos, anidados y con miembros compuestos. Esta separación entre el modelo conceptual que la aplicación utiliza y el esquema de almacenamiento de la base de datos es un poderoso concepto que simplificará enormemente la creación y mantenimiento de aplicaciones de bases de datos.
El exponer vistas de cliente a través de un Proveedor de Datos ADO.NET permite mantener el modelo de programación familiar de ADO.NET, aprovechando la inversión en código, herramientas y conocimiento existente y dicho proveedor pasa a formar parte del popular conjunto de Proveedores de Datos disponibles.
El Entity Client aprovecha la inversión e investigación significativa que ya existe en el campo de la teoría de bases de datos relacionales. Las actualizaciones, por ejemplo, se realizan aplicando técnicas de mantenimiento de vistas bien definidas a las "update views" para así producir un conjunto de expresiones delta que se combinan con "query views" para producir expresiones de actualización.
Para quienes prefieren trabajar con datos como objetos CLR tipificados en lugar de registros sin tipo, ADO.NET Entities incluye "Object Services", el cual se basa en Entity Client y permite realizar queries y traer resultados en la forma de "Clases de Datos" cuya identidad y cambios son administrados por el desarrollador.
"LINQ" significa "Language INtegrated Query" y, como su nombre lo indica, integra conceptos de consultas directamente en los lenguajes de programación, permitiendo que el código de acceso a datos sea verificado por el compilador y las herramientas de desarrollador, como Intellisense para hacer que los desarrolladores escriban queries. Esto, junto con conceptos de modelos conceptuales (como Entidades), contribuye a reducir el abismo entre aplicaciones y datos.
LINQ tiene soporte completo en el ADO.NET Entity Framework a través de "LINQ to Entities". Este último es parte de la capa de Object Services, el cual permite construir queries a través de expresiones de lenguaje tipificadas así como sentencias textuales de Entity SQL. Esto significa que las mismas vistas conceptuales de cliente están disponibles a través de patrones de programación ADO.NET existentes o a través del consumo de Object Services utilizando ya sea queries textuales ad-hoc o queries integrados en el lenguaje.
Entity Data Model: solo el principio
Microsoft está apostando fuerte con respecto al Entity Framework y el Entity Data Model en particular. Se espera que haya cada vez más y más servicios en SQL Server, así como diversas tecnologías, que aprovechen el Entity Data Model como una forma natural de describir datos en términos de conceptos del mundo real.
Para mi, como desarrollador, este es un momento fascinante en el que finalmente podré pensar y trabajar con la libertad que me brinda este modelo conceptual y concentrarme en dar mayor funcionalidad a mis aplicaciones, ser mucho más productivo y satisfacer las necesidades de mis clientes de formas mucho más robustas y creativas.
Julio.