Linq Para SQL Parcial 5

Embed Size (px)

Citation preview

5.1. Conceptos de LINQUnidad V - Acceso a datos con LINQ5.1. - Conceptos de LINQObjetivo General.Usar la herramienta de acceso a datos de LINQ en conjunto con el lenguaje de desarrollo para hacer consultas directas a la base de datos y la administracin centralizada de datos.Objetivo Especfico.Identificar patrones y conceptos generales del uso de LINQ para el acceso a datos.

Introduccin.El software es simple y se compone de dos cosas: cdigo y datos. Escribir software no es tan simple, y una de las mayores actividades que implica es escribir cdigo que maneje datos.Para escribir cdigo, se puede escoger de entre una variedad de lenguajes de programacin. El lenguaje seleccionado para una aplicacin puede depender del contexto del negocio, de las preferencias del desarrollador, de las habilidades del equipo de desarrollo, del sistema operativo, o de polticas de la empresa.Cualquiera que sea el lenguaje seleccionado, en algn punto tendr que tratar con datos. Estos datos pueden estar en archivos o en un disco, en tablas dentro de una base de datos, o documentos XML provenienter de la web, o a menudo se tiene que tratar con una combinacin de todos ellos. Finalmente, administrar datos es un requerimiento para cualquier proyecto de software.Ya que trabajar con datos es una tarea comn para los desarrolladores, se espera una plataforma de desarrollo de software rica como .NET Framework para proveer una forma fcil de hacerlo. .NET provee un amplio soporte para trabajar con datos. Sin embargo, algo an tiene que lograrse: una mayor integracin entre el lenguaje y los datos. Aqu es donde entran LINQ para Objetos, LINQ para XML y LINQ para SQL.1. Qu es LINQ?Suponga que est escribiendo una aplicacin usando .NET. Son altas las probabilidades de que en algn punto tendr que usar persistencia de objetos a una base de datos, consultar la base de datos, y cargar los resultados de regreso a los objetos. El problema es que en muchos casos, al menos con las bases de datos relacionales, hay una brecha entre el lenguaje de programacin y la base de datos.Se han hecho buenos intentos para proveer bases de datos orientadas a objetos, los cuales estaran ms cercanos a plataformas orientadas a objetos y lenguajes de programacin como C# y VB .NET. Sin embargo, despus de todos estos aos, las bases de datos relacionales an son evasivar, y todava tiene que lidiar con el acceso a datos y la persistencia en todos los programas.La motivacin original detrs de LINQ era atender las dificultades tcnicas y conceptuales encontradas, cuando se usan bases de datos con lenguajes de programacin .NET. Con LINQ, la intencin de Microsoft fue proveer una solucin para el problema del mapeo relacional de objetos, as como simplificar la interaccin entre los objetos y los orgenes de datos. LINQ eventualmente evolucion hacia un conjunto de herramientas de consulta de propsito general integradas al lenguaje. Este conjunto de herramientas puede ser usado para acceder datos que vienen de objetos en memoria (LINQ para Objetos), bases de datos (LINQ para bases de datos), XML (LINQ para XML), un sistema de archivos o cualquier otro origen.1.1. Panorama general.LINQ podra ser el enlace faltante entre el mundo de los datos y el mundo de los lenguajes de programacin de propsitos generales. LINQ unifica el acceso a datos, cualquiera sea el origen de datos, y permite combinar datos de diferentes tipos de orgenes. Permite consultar y configurar operaciones, de manera similar a lo que las sentencias SQL ofrecen para las bases de datos. LINQ, sin embargo, integra consultas directamente dentro de los lenguajes .NET tales como C# y VB .NET a travs de un conjunto de extensiones a esos lenguajes: LINQ significa Consulta Integrada al Lenguaje (Language-INtegrated Query).Antes de LINQ se tena que lidiar con diferentes lenguajes como SQL, XML, o XPath junto con varias tecnologas y APIs como ADO .NET o System.Xml en cada aplicacin escrita usando lenguajes de propsitos generales tales como C# o VB .NET. Y por supuesto que este enfoque tena muchas desventajas (Similar a ordenar la cena en un idioma y pedir las bebidas en otro idioma). LINQ une varios mundos y ayuda a evitar las dificultades que usualmente se tendran en el camino de un mundo a otro: usar XML con objetos, objetos con datos relacionales, y datos relacionales con XML son algunas de las tareas que LINQ simplificar.Uno de los aspectos clave de LINQ es que fue diseado para ser usado contra cualquier tipo de objetos u origen de datos y para proveer un modelo de programacin consistente para hacerlo. La sintaxis y los conceptos son los mismos entre todos sus usos. Una vez aprendido cmo usar LINQ sobre un arreglo o una coleccin, tambin se pueden conocer la mayora de conceptos necesarios para aprovechar LINQ con una base de datos o con un archivo XML.Otro aspecto importante de LINQ es que cuando lo usa, trabaja en un mundo fuertemente tipeado. Los beneficios incluyen una revisin en tiempo de compilacin para las consultas, as como oportunas sugerencias de la caracterstica IntelliSense de Visual Studio.LINQ cambiar significativamente algunos aspectos sobre cmo manejar y manipular los datos con la aplicacin y los componentes, ya que LINQ es un paso hacia un modelo de programacin ms declarativo. Tal vez se pregunte en el futuro no tan distante por qu tena que escribir tantas lneas de cdigo.Hay una dualidad en LINQ. Puede concebir a LINQ como dos partes complementarias: un conjunto de herramientas que trabajan con datos, y un conjunto de extensiones de lenguajes de programacin.1.2. LINQ como un conjunto de herramientas.LINQ ofrece numerosas posibilidades y cambiar significativamente algunos aspectos de cmo se manejan y manipulan los datos con las aplicaciones y componentes. LINQ contiene varios proveedores, entre los cuales se tienen LINQ para Objetos, LINQ para SQL, y LINQ para XML. Los tres proveedores estn construidos en la cima de la base comn de LINQ. Estos proveedores conforman una coleccin de bloques integrados que incluyen operadores de consulta, expresiones de consulta, y rboles de expresiones, que le permite al juego de herramientas de LINQ ser extensible.Otras variantes de LINQ pueden ser creadas para proporcionar acceso a diversas clases de orgenes de datos. Las implementaciones de LINQ sern liberadas por los vendedores de software, y tambin se pueden crear implementaciones propias. Se puede conectar un amplio arreglo de orgenes de datos dentro de LINQ, incluyendo el sistema de archivos, directorio activo, VML, la bitcora de eventos de Windows o cualquier otro origen de datos o API. Esto es bueno porque se puede obtener beneficio de las caractersticas de LINQ con varios de los orgenes de datos con los cuales se trabaje cada da. De hecho, Microsoft ya ofrece ms proveedores de LINQ que slo LINQ para objetos, LINQ para SQL y LINQ para XML.La figura siguiente muestra cmo se representan los bloques construidos y el conjunto de herramientas en un diagrama.

Los proveedores LINQ presentados no son herramientas independientes, y pueden ser usados directamente en los lenguajes de programacin. Esto es posible porque el marco de trabajo de LINQ viene como un conjunto de extensiones de lenguaje. Este es el segundo aspecto de LINQ.1.3. LINQ como extensiones del lenguaje.LINQ permite acceder informacin al escribir consultas sobre varios orgenes de datos y provee el mismo tipo de capacidades que ofrece SQL, pero en el lenguaje de programacin de su eleccin, tal como se muestra a continuacin:

El cdigo anterior demuestra lo que se necesita escribir para extraer datos de una base de datos y crear un documento XML a partir de l. Imagine lo que hara para hacer lo mismo sin LINQ, y se dar cuenta cmo las cosas son ms fciles y ms naturales con LINQ. Con las palabras reservadasfrom, where, orderbyyselecten el listado, es obvio que C# ha sido extendido para habilitar las consultas integradas en el lenguaje.En la figura siguiente se muestra una tpica consulta integrada al lenguaje que es usada para hablar con los objetos, XML, o tablas de datos.

La consulta en la figura es expresada en C# y no en un nuevo lenguaje. LINQ no es un nuevo lenguaje. Est integrado en C# y VB .NET. Adems, LINQ puede ser usado para evitar enredar su lenguaje de programacin .NET con SQL, XML u otro lenguaje de datos especfico. El conjunto de extensiones de lenguaje que viene con LINQ habilita las consultas sobre varios tipos de almacenes de datos para ser formulados justo en los lenguajes de programacin. Piense en LINQ como un control universal remoto, si desea. A veces, lo usar para consultar una base de datos; en otros, consultar un documento XML. Pero har todo esto en su lenguaje favorito, sin tener que cambiar a otro como SQL o XQuery.2. Para qu se necesita LINQ?Se ha proporcionado un panorama general de LINQ. La gran pregunta en este punto es: para qu se necesita una herramienta como LINQ? Qu hace inconveniente a las herramientas anteriores? Fue LINQ creado slo para trabajar con lenguajes de programacin, datos relacionales y XML, de forma ms conveniente?En el inicio del proyecto LINQ era un hecho sencillo: la vasta mayora de aplicaciones que eran desarrolladas accedan datos o hablaban con las bases de datos relacionales. Consecuentemente, para programar aplicaciones, aprender un lenguaje tal como C# no es suficiente. Tambin tiene que aprender otro lenguaje como SQL, y la API que lo une con C# para formar la aplicacin completa.2.1. Problemas comunes.El uso frecuente de bases de datos en aplicaciones requiere que el Framework de .NET trate sobre la necesidad de APIs que pueden acceder los datos almacenados en ellas. Por supuesto, esto ha sido el caso desde la primera aparicin de .NET. La librera de clases del Framework de .NET (FCL) incluye ADO .NET, lo cual le proporciona una API para acceder bases de datos relacionales y representar datos en memoria. Esta API consiste en clases tales como SqlConnection, SqlCommand, SqlReader, DataSet, y DataTable, por mencionar algunas. El problema con esas clases es que ellas obligan a los desarrolladores a trabajar explcitamente con las tablas, registros y columnas, mientras los lenguajes modernos como C# y VB .NET utilizan paradigmas orientados a objeto.Ahora que el paradigma orientado a objeto es el modelo dominante en el desarrollo de software, los desarrolladores incurren en una gran cantidad de sobrecarga en mapearlo a otras abstracciones, especficamente bases de datos relacionales y XML. El resultado es que mucho tiempo es gastado en escribir cdigo de fontanera. El eliminar esta molestia incrementara la productividad en la programacin intensiva de datos, lo cual LINQ ayuda a hacer.Pero no es slo la productividad, sino que adems impacta en la calidad. Escribir cdigo tedioso y cdigo de plomera frgil puede conducir a defectos insidiosos en el software o a degradar el rendimiento.A continuacin se muestra un acceso a datos tpico en un programa .NET. Al observar los problemas que existen con el cdigo tradicional, ser capaz de ver cmo LINQ viene al rescate.

Con solo dar un vistazo a este cdigo podemos enumerar varias limitaciones al modelo: A pesar de que se desea realizar una tarea simple, se deben realizar varios pasos y se requiere escribir mucho cdigo. Las consultas son expresadas como cadenas citadas(1), lo que significa que evitan todo tipo de revisiones en tiempo de compilacin. Qu sucede si el cdigo no contiene una consulta SQL vlida? Qu sucede si una columna ha sido renombrada en la base de datos? Lo mismo puede decirse de los parmetros(2)y de los conjuntos de resultados(3): estn dbilmente definidos. Son las columnas del tipo de datos que se espera? Tambin, estamos seguros que estamos usando el nmero correcto de parmetros? Estn los nombres de los parmetros en sincrona entre la consulta y la declaracin de parmetros? Las clases que usamos estn dedicadas a SQL Server y no pueden ser usadas con otro servidor de bases de datos. Naturalmente, podemos usar DbConnection y sus derivados para evitar este tema, pero eso resolvera solamente la mitad del problema. El Verdadero problema es que SQL tiene tantos dialectos especficos a los proveedores y tipos de datos. El SQL que escribimos para un DBMS determinado es casi seguro que fallar para otro diferente.Existe otra solucin. Podemos usar un generador de cdigo de alguna de las varias herramientas de objetos mapeados relacionados disponibles. El problema es que esas herramientas tampoco son perfectas y tienen sus propias limitaciones. Por ejemplo, si son diseadas para acceder a una base de datos, la mayor parte del tiempo no maneja otros orgenes de datos tales como documentos XML. Tambin, una cosa que los proveedores de lenguajes como Microsoft pueden hacer y que los vendedores de herramientas de mapeo no pueden es integrar el acceso a datos y las caractersticas de consulta justo en sus lenguajes. Las herramientas de mapeo a los sumo se presentan como una solucin parcial del problema.La motivacin para LINQ tiene doble propsito: Microsoft an no tena una solucin de mapeo de datos, y con LINQ tena la oportunidad de integrar consultas dentro de sus lenguajes de programacin. Esto poda eliminar la mayora de las limitaciones identificadas en el cdigo anterior.La idea principal es que al usar LINQ se pueda ganar acceso a cualquier origen de datos al escribir consultas como la mostrada a continuacin, directamente en el lenguaje de programacin de uso diario.

En esta consulta, los datos pueden estar en memoria, en una base de datos, en un documento XML, o en cualquier otro lugar; la sintaxis permanecera similar, si no exactamente la misma. Este tipo de consultas puede ser usado con mltiples tipos de datos y diferentes orgenes de datos, gracias a las caractersticas de extensibilidad de LINQ. Por ejemplo, en el futuro posiblemente veamos una implementacin de LINQ para consultar un subsistema de archivos o para llamar servicios web.

2.2. Tratando el paradigma del desajuste.Continuemos revisando por qu es necesario LINQ. El hecho que los desarrolladores de aplicaciones modernas tengan que atender simultneamente con lenguajes de programacin de propsitos generales, datos relaciones, SQL, documentos XML, XPath, y as por el estilo, significa que se necesitan dos cosas: Ser capaz de trabajar con cualquiera de esas tecnologas o lenguajes individualmente. Mezclar y hacer coincidirlos para construir soluciones ricas y coherentes.El problema est en que la programacin orientada a objetos, el modelo de bases de datos relacionales, y XML - por mencionar algunos - no fueron originalmente construidos para trabajar juntos. Representan diferentes paradigmas que no funcionan bien entre s.Qu es el desajuste de impedancia?Los datos son manipulados generalmente por software de aplicaciones escritas usando lenguajes de programacin orientados a objetos tales como C#, VB .NET, Java, Delphi y C++. Pero traducir un objeto grfico en otra representacin, tal como tuplas de una base de datos relacional requiere a menudo de cdigo tedioso.El problema general que LINQ trata ha sido expresado por Microsoft de esta manera: "Datos != Objetos". Ms especficamente, con LINQ para SQL: "Datos Relacionales != Objetos". Los mismo aplica con LINQ para XML: "Datos XML != Objetos". Deberamos agregar "Datos XML != Datos Relacionales".El trminodesajuste de impedanciase refiere a la incompatibilidad entre sistemas y describe una habilidad inadecuada de un sistema para acomodar los insumos provenientes de otro sistema. A pesar que el trmino se origin en el campo de la ingeniera elctrica, ha sido generalizado y usado como un trmino tcnico en anlisis de sistemas, electrnica, fsica, ciencias de la computacin e informtica.Mapeo de objetos relacionalesSi se habla del paradigma orientado a objetos y el paradigma relacional, el desajuste existe en varios niveles. Veamos algunos.Las bases de datos relacionales y los lenguajes orientados a objetos no comparten el mismo conjunto de tipos de datos primitivos. Por ejemplo, las cadenas usualmente tienen una longitud delimitada en las bases de datos, lo cual no es el caso en C# o VB .NET, Esto puede ser un problema si intenta persistir una cadena de 150 caracteres en un campo de tabla que acepta solamente 100 caracteres. Otro ejemplo sencillo es que las mayoras de bases de datos no tienen un tipo de datos booleano, mientras que es frecuente el uso de valores verdadero/falso en muchos lenguajes de programacinLas teoras de la programacin orientada a objetos y relacionada tienen diferentes modelos de datos. Por razones de rendimiento y debido a su naturaleza intrnseca, las bases de datos relacionales son usualmentenormalizadas. La normalizacin es un proceso que elimina la redundancia, organiza datos eficientemente, reduce el potencial de animalas durante las operaciones de datos y mejora la consistencia de datos. La normalizacin resulta en una organizacin de datos que es especfica al modelo de datos relacional. Esto le impide un mapeo directo de tablas y registros a objetos y colecciones. Las bases de datos relacionales estn normalizadas en tablas y relaciones, mientras los objetos usan herencia, composicin, y grficos de referencia compleja. Un problema comn existe debido a que las bases de datos relacionales no tienen conceptos como herencia: mapear una jerarqua de clases a una base de datos relacional requiere el uso de "trucos".Los modelos de programacin. En SQL se escriben consultas, y por tanto se tiene una forma declarativa y de mayor nivel para expresar el conjunto de datos sobre los que se tiene inters. Con lenguajes de programacin imperativos tales como C# o VB .NET, es necesario escribir ciclosfor, sentenciasif, y as por el estilo.Encapsulamiento. Los objetos son autocontenidos e incluyen tanto el comportamiento como los datos. En las bases de datos, los registros de datos no tienen comportamiento por s mismos. Es posible actuar sobre registros de una base de datos slo por medio del uso de consultas SQL o de procedimientos almacenados. En las bases de datos relacionales, el cdigo y los datos estn claramente separados.El desajuste es el resultado de las diferencias entre el modelo de base de datos relacional y la tpica jerarqua de clases orientadas a objetos. Se podra decir que las bases de datos relacionales son de Marte y los objetos son de Venus.Tomemos un ejemplo sencillo como el mostrado en la figura siguiente.

Se tiene un modelo de objetos que se desea mapear hacia un modelo relacional.Conceptos tales como herencia o composicin no son soportados directamente por las bases de datos relacionales, lo cual significa que no se puede representar los datos de la misma forma en ambos modelos. Puede ver en el ejemplo que varios objetos y tipos de objetos pueden ser mapeados a una sola tabla.An si se deseara persistir un modelo de objetos como el que se presenta hacia una nueva base de datos relacional, no se podra usar mapeo directo. Por ejemplo, por razones de rendimiento y para evitar duplicidad, es mucho mejor en este caso crear slo una tabla en la base de datos. Una consecuencia de hacer esto, sin embargo, es que los datos que vienen de la tabla en la base de datos no pueden ser fcilmente usados para repoblar un grfico de objetos en memoria. Lo que se gana en un lado se pierde en el otro.Se debe ser capaz de disear esquemas de base de datos o un modelo de objetos para reducir el desajuste en ambos mundos, pero nunca se podr eliminar debido a las diferencias intrnsecas entre los dos paradigmas. A veces ni siquiera se tiene alternativa. A menudo, el esquema de bases de datos ya est definido, y en otras ocasiones se tiene que trabajar con objetos definidos por alguien ms.El problema complejo de integrar orgenes de datos con programas incluye ms que slo leerlas de y escribirlas a una fuente de datos. Cuando la programacin usa un lenguaje orientado a objetos, normalmente se desea que las aplicaciones usen un modelo de objetos que sea una representacin conceptual del dominio del negocio, en lugar de estar atadas directamente a la estructura relacional. El problema es que en algn punto se necesita hacer que el modelo de objetos y el modelo relacional trabajen juntos. Esto no es una tarea fcil porque los lenguajes de programacin orientados a objetos y .NET incluyen clases entidades, reglas de negocio, relaciones complejas y herencia, mientras que el origen de datos relacional incluye tablas, filas, columnas y llaves (primarias y secundarias).Una solucin tpica para unir lenguajes orientados a objetos y base de datos relacionales es elmapeo de objetos relacional. Esto se refiere al proceso de mapear el modelo de base de datos relacional al modelo de objetos, usualmente en ambos lados. Mapear puede ser definido como el acto de determinar cuntos objetos y sus relaciones son persistentes en almacenamiento de datos permanentes, en este caso bases de datos relacionales.Las bases de datos no se mapean de forma natural al modelo de objetos. Los mapeadores objeto-relacional son soluciones automatizadas para tratar el problema del desajuste. Para acortar la historia: se proporciona un mapeador objeto-relacional con clases, base de datos y configuraciones de mapeo, y el mapeador se encarga del resto. Genera consultas SQL, llena los objetos con datos de la base de datos, los persiste en la base de datos, y as por el estilo.Como puede imaginar, ninguna solucin es perfecta, y los mapeadores objeto-relacional podran ser mejorados. Algunas de sus principales limitaciones son: Se requiere un buen conocimiento de herramientas antes de poder usarlos eficientemente y evitar problemas de desempeo. El uso ptimo todava requiere conocimiento de cmo trabajar con una base de datos relacional. Las herramientas de mapeo no siempre son tan eficientes como el cdigo escrito a mano. No todas las herramientas vienen con soporte para validacin en tiempo de compilacin.Mltiples herramientas de mapeo objeto-relacional estn disponibles para .NET. Hay una seleccin de productos de cdigo libre, gratuitos y comerciales.Mapeo de objetos XML.Anlogo a la impedancia de desajuste objeto-relacional, un desajuste similar tambin existe entre objetos y XML. Por ejemplo, el tipo sistema descrito en la especificacin de esquemas W3C y XML no tiene relacin de uno a uno con el tipo sistema del marco de trabajo .NET. Sin embargo, usar XML en una aplicacin .NET no es mayor problema porque ya se tienen APIs que tratan con esto bajo el espacio de nombresSystem.Xml, al igual que soporte integrado para serializacin y deserializacin de objetos.Sin embargo, mucho cdigo tedioso es requerido la mayora de las veces para hacer an cosas sencillas sobre documentos XML.Dado que XML se ha vuelto tan penetrante en el mundo del software moderno, algo se tena que hacer para reducir el trabajo requerido para tratar con XML en los lenguajes de programacin.Cuando se mira en esos dominios, es destacable cunta diferencia existe. El origen principal de contencin relaciona los siguientes hechos: Las bases de datos relacionales estn basadas en el lgebra relacional y son todas sobre tablas, filas, columnas y SQL. XML es sobre documentos, elementos, atributos, estructuras de jerarqua, y XPath. Los lenguajes de programacin de propsitos generales orientados a objetos y .NET viven en un mundo de clases, mtodos, propiedades, herencia y ciclos.Muchos conceptos son especficos a cada dominio y no tienen mapeo directo hacia el otro dominio. La figura siguiente proporciona un panorama general de los conceptos usados en .NET y la programacin orientada a objetos, en comparacin con los conceptos usados en las fuentes de datos tales como XML o bases de datos relacionales. Demasiado a menudo, los programadores tienen que hacer un poco de trabajo de albailera para unir estos dominios diferentes. Diferentes APIs para cada tipo de datos caus que los desarrolladores invirtieran una exagerada cantidad de tiempo aprendiendo cmo escribir, depurar y reescribir cdigo frgil.

Los culpables tradicionales que arruinan la lgica son malas cadenas de consultas SQL o etiquetas XML, o contenido que no se revisa hasta el tiempo de ejecucin. Los lenguajes .NET tales como C# y VB .NET ayudan a los desarrolladores y proporcionan recursos tales como IntelliSense, cdigo fuertemente tipeado, y revisiones en tiempo de compilacin. Sin embargo, esto puede arruinarse si se empieza a incluir consultas SQL mal formadas o fragmentos de XML en el cdigo, ninguno de los cuales es validado por el compilador.Una solucin exitosa requiere unir las diferentes tecnologas y solucionar el desajuste de impedancia objeto-persistencia, un problema que es todo un reto y consume muchos recursos. Para resolver este problema, se debe resolver los siguientes puntos entre .NET y los elementos de origen de datos: Fundamentalmente diferentes tecnologas. Diferentes cojuntos de habilidades. Diferentes personas y propietarios para cada una de las tecnologas. Diferentes modelos y principios de diseo.Algunos esfuerzos han sido hechos para reducir el desajuste de impedancia al unir algunas piezas de un mundo en otro. Por ejemplo, SQLXML 4.0 une SQL con XSD; System.Xml abarca XML/XML DOM/XSL/XPath y CLR; la API ADO .NET une SQL y los tipos de datos CLR; y SQL Server 2005 incluye integracin con CLR. Todos estos esfuerzos son prueba que la integracin de datos es esencial; sin embargo, representan movimientos diferentes sin una base comn, lo cual los hace difciles de usar juntos. LINQ, por el contrario, ofrece una infraestructura comn para tratar los desajustes de impedancia.2.3. LINQ al rescate.Para tener xito en el uso de objetos y bases de datos relacionales juntos, es necesario entender ambos paradigmas, junto con sus diferencias, y entonces efectuar concesiones inteligentes basadas en ese conocimiento. El objetivo principal de LINQ para SQL es liberarse de, o al menos reducir, la necesidad de preocuparse por esas limitaciones.Un desajuste de impedancia obliga a escoger un lado o el otro como el lado "primario". Con LINQ, Microsoft selecciona el lado del lenguaje del programador, debido a que es ms fcil adaptar los lenguajes C# y VB .NET que cambiar SQL o XML, el objetivo es hacia las capacidades profundamente integradas de consultas de datos y de manipulacin de lenguajes dentro de los lenguajes de programacin.LINQ quita muchas de las barreras entre objetos, bases de datos y XML. Permite trabajar con cada uno de estos paradigmas usando los mismos recursos integrados en el sistema. Por ejemplo, se puede trabajar con datos XML y datos provenientes de una base de datos relacional dentro de la misma consulta.Debido a que el cdigo vale ms que mil palabras, a continuacin se presenta una muestra sencilla del poder de LINQ para recuperar datos de una base de datos y crear un documento XML en una sola consulta. El cdigo siguiente crea una alimentacin RSS basada en datos relacionales.

Observe cmo LINQ facilita trabajar con datos relacionales y XML en la misma porcin de cdigo. Si ya ha efectuado este tipo de trabajos antes, debera ser obvio que este cdigo es muy legible y conciso en comparacin con las soluciones disponibles antes del aparecimiento de LINQ.3. Objetivos de diseo y orgenes de LINQ.Es importante conocer claramente lo que pretenda lograr Microsoft con LINQ. Por esta razn se revisarn los objetivos de diseo del proyecto LINQ. Tambin es interesante saber de donde toma sus races LINQ y entender los vnculos con otros proyectos de los cuales habr escuchado.LINQ no es un proyecto reciente de Microsoft en el sentido que hereda muchas caractersticas de trabajo de investigacin y desarrollo hecho sobre los ltimos aos.3.1. Los objetivos del proyecto LINQ.La tabla siguiente muestra los objetivos de diseo que Microsoft defini para el proyecto LINQ, con el objeto de proporcionar un entendimiento claro de lo que ofrece LINQ.ObjetivoMotivacin

Integrar objetos, datos relacionales y XML.Sintaxis de consulta unificada entre orgenes de datos para evitar diferentes lenguajes de diferentes orgenes de datos.Un solo modelo para procesar todos los tipos de datos, sin importar el origen o la representacin en memoria.

Potencia similar a SQL y XQuery en C# y VB .NET.Integrar habilidades de consulta justo dentro de los lenguajes de programacin.

Modelo de extensibilidad para lenguajes.Habilitar la implementacin de otros lenguajes de programacin.

Modelo de extensibilidad para mltiples orgenes de datos.Ser capaz de acceder otros orgenes de datos, adems de las bases de datos relacionales o documentos XML.Permitir a otros marcos de trabajo habilitar el soporte a LINQ para sus propias necesidades.

Seguridad de tipo.Revisin de tipo en tiempo de compilacin para evitar problemas que antes eran descubiertos slo en tiempo de ejecucin.El compilador atrapar errores en sus consultas.

Soporte extensivo de IntelliSense (habilitado por un fuerte tipeado).Asistir a los desarrolladores cuando escriben consultas para mejorar la productividad y para ayudarles a elevar la velocidad con la nueva sintaxis.El editor lo guiar cuando escriba consultas.

Soporte de depurador.Permite a los desarrolladores depurar consultas LINQ paso a paso y con abundante informacin de depuracin.

Construido sobre los fundamentos de C# a.0 y 2.0, VB .NET 7.0 y 8.0.Reutiliza las ricas caractersticas que han sido implementadas en las versiones previas de los lenguajes.

Corre sobre CLR .NET 2.0.Evita la necesidad de un nuevo tiempo de ejecucin y molestias innecesarias de instalacin.

Ser 100% compatible con versiones anteriores.Ser capaz de usar colecciones estndar y genricas, enlace de datos, controles web y Windows existentes, etc.

La primera caracterstica presentada en la tabla anterior es la habilidad de tratar con varios tipos y orgenes de datos. LINQ se empaca con implementaciones que soportan consultas sobre colecciones de objetos regulares, bases de datos, entidades y orgenes XML. Debido a que LINQ soporta una rica extensibilidad, los desarrolladores pueden tambin integrarlo fcilmente con otros orgenes de datos y proveedores.Otra caracterstica esencial de LINQ consiste en ser fuertemente tipeado. Esto significa lo siguiente: Se obtiene revisin en tiempo de compilacin para todas las consultas. A diferencia de las sentencias SQL actuales, donde tpicamente slo se encuentra que algo est mal hasta el tiempo de ejecucin, se puede revisar durante el desarrollo que el cdigo est correcto. El beneficio directo es una reduccin del nmero de problemas descubiertos ms tarde en produccin. La mayora de las veces, estos temas son debido a factores humanos. Las consultas fuertemente tipeadas permiten detectar errores cometidos por el desarrollador a cargo de la digitacin. Se obtiene IntelliSense dentro de Visual Studio cuando se escriben consultas LINQ. Esto no slo hace ms fcil la escritura de cdigo, sino que tambin hace ms fcil trabajar sobre colecciones simples y complejas, as como modelos de objetos orgenes de datos.3.2. Un poco de historia.LINQ es el resultado de un largo proceso de investigacin dentro de Microsoft. Varios proyectos que involucran evolucin de lenguajes de programacin y mtodos de acceso a datos pueden ser considerados los padres de LINQ para Objetos, LINQ para XML (anteriormente conocido como XLinq), y LINQ para SQL (anteriormente conocido como DLinq).C (o el lenguaje C-Omega).C (pronunciado "c-omega") fue un proyecto de Microsoft Research que extiende el lenguaje en varias reas, sobresaliendo las siguientes: Una extensin de flujo de control para concurrencia de rea amplia asncrona (anteriormente conocido como C# Polifnico). Una extensin de tipo de datos para manipulacin de XML y base de datos (anteriormente conocido como Xen y X#).C cubri ms de lo que viene con LINQ, pero gran parte de lo que ahora es incluido como parte de la tecnologa LINQ ahora est presente en C. El proyecto C fue concebido para experimentar con consultas integradas, mezclando C# y SQL, C# y XQuery, etc. Esto fue realizado por investigadores como Erik Meijer, Wolfram Schulte y Gavin Bierman, quienes publicaron varios trabajos sobre el tema.C fue liberado como un avance en 2004. Mucho ha sido aprendido desde ese prototipo, y pocos meses despus, Anders Hejlsberg, jefe de diseo del lenguaje C#, anunci que Microsoft estara trabajando en la aplicacin de ese conocimiento en C# y en otros lenguajes de programacin. Anders dijo en ese momento que su inters particular en los ltimos dos aos haba sido pensar profundamente sobre el gran desajuste de impedancia entre los lenguajes de programacin - C# en particular - y el mundo de los datos. Esto incluye bases de datos y SQL, pero tambin XML y XQuery, por ejemplo.Las extensiones de C haca el sistema tipo .NET y hacia el lenguaje C# fueron los primeros pasos hacia un sistema unificado que tratara las consultas estilo SQL, consultas de conjuntos de resultados, y contenido XML como miembros de pleno derecho del lenguaje. C introduce el tipostream, el cual es anlogo al tipoSystem,Collections.Genericde .NET Framework 2.0. C tambin define constructores para tuplas tipeadas (llamadasanonymus structs), los cuales son similares a los tipos annimos que se tienen en C# 3.0 y VB .NET 9.0. Otra cosa que soportaba C es XML embebido, algo que se pudo ver en VB .NET 9.0 (pero no en C# 3.0).Object SpacesLINQ para SQL no es el primer intento de Microsoft para un mapeo de objetos-relaciones. Otro proyecto con una fuerte relacin con LINQ fue Object Spaces.El primer avance del proyecto Object Spaces apareci en la presentacin de ADO .NET PDC 2001. Object Spaces fue un conjunto de APIs de acceso a datos. Permitan que los datos fueran tratados como objetos, independiente de los datos subyacentes almacenados. Object Spaces tambin introdujo OPath, un lenguaje de consultas de objeto propietario. En 2004, Microsoft anunci que Object Spaces dependa del proyecto WinFS (un proyecto para sistemas de archivos relacionados que Microsoft haba estado desarrollando para Windows. Fue cancelado en 2006), y por tanto sera pospuesto en el plazo Orcas (el siguiente lanzamiento despus de .NET 2.0 y Visual Studio 2005). Ningn nuevo lanzamiento se dio despus de eso. Todos se dieron cuenta que Object Spaces nunca vera la luz del da cuando Microsoft anunci que WinFS no sera incluido en la primera liberacin de Windows Vista.Implementacin XQuery.Similar a lo que sucedi con Object Spaces y por el mismo tiempo, Microsoft haba empezado a trabajar en un procesador XQuery. Un avance fue incluido en la primera liberacin beta de la versin 2.0 de .NET Framework, pero eventualmente se decidi no incluir una implementacin XQuery del lado del cliente en la versin final. Un problema con XQuery es que fue un lenguaje adicional que tendramos que aprender expecficamente para tratar con XML.Por qu todos estos pasos hacia atrs? Por qu Microsoft aparentemente detuvo el trabajo sobre esas tecnologas? La causa salt a la vista en PDC 2005, cuando el proyecto LINQ fue anunciado.LINQ haba sido diseado por Anders Hejlsberg y otros en Microsoft para tratar el problema del desajuste de impedancia desde dentro de los lenguajes de programacin tales como C# y VB .NET. Con LINQ se puede consultar casi todo. Esto es porque Microsoft favoreci LINQ en lugar de continuar invirtiendo en proyectos separados como Object Spaces o soporte para XQuery en el lado del cliente.Como habr visto, LINQ tiene una rica historia detrs de l, y se ha beneficiado de todos los trabajos de investigacin y desarrollo de los proyectos previos y ahora extintos.5.2. Conociendo los patrones de acceso a datos de LINQUnidad V - Acceso a datos con LINQ.5.2. Conociendo los patrones de acceso a datos de LINQ.Objetivo General.Usar la herramienta de acceso a datos de LINQ en conjunto con el lenguaje de desarrollo para hacer consultas directas a la base de datos y la administracin centralizada de datos.

Objetivo Especfico.Identificar los patrones exactos para la manipulacin de datos en los casos de consultas complejas y operaciones de mantenimiento.

1. LINQ para Objetos: consultando colecciones en memoria.Antes de iniciar, es necesario revisar todo lo que se necesita para probar el cdigo. A continuacin se presentan los requerimientos que se deben satisfacer.1.1. Soporte para el compilador y .NET Framework, y software requerido.LINQ es entregado como parte de la olaOrcas, lo cual incluye Visual Studio 2008 y .NET Framework 3.5. Esta versin del marco de trabajo viene con libreras adicionales y actualizadas, as como nuevos compiladores para los lenguajes C# y VB .NET, pero permanecen compatibles con .NET Framework 2.0.Las caractersticas de LINQ son asuntos del compilador y de las libreras, no del runtime. Es importante entender que a pesar que los lenguajes C# y VB .NET han sido enriquecidos y algunas nuevas libreras han sido agregadas al .NET Framework, el runtime de .NET (el CLR) no necesit evolucionar. Nuevos compiladores fueron necesarios para C# 3.0 y VB .NET 9.0, pero el runtime requerido an es la versin 2.0 no modificada. Esto significa que las aplicaciones que haya construido usando LINQ pueden correr en un runtime .NET 2.0 (sin embargo, .NET 2.0 Service Pack 1 es necesario para que funcione LINQ para SQL).LINQ y LINQ para XML, o al menos un subconjunto de ellos, son soportados por las liberaciones actuales del runtime Silverlight. Estn disponibles en los espacios de nombreSystem,LinqySystem.Xml.Linq.Para configurar la computadora y poder ejecutar el cdigo, se requiere instalar lo siguiente:Al menos una de las siguientes versiones de Visual Studio: Visual C# 2008 Express Edition. Visual Basic 2008 Express Edition. Visual Web Developer 2008 Express Edition. Visual Studio 2008 Standard Edition o superior.Si se quiere ejecutar LINQ para SQL, se requiere uno de los siguientes: SQL Server 2005 Express Edition o SQL Server 2005 Compact Edition (incluido con la mayora de versiones de Visual Studio). SQL Server 2005. SQL Server 2000a. Una versin posterior de SQL Server (los nuevos tipos de datos proporcionados por SQL Server 2008 no son soportados en la primera liberacin de LINQ para SQL).1.2. Consideraciones de lenguaje.Se asume que tiene conocimiento del lenguaje de programacin C#. Por cuestiones de simplicidad, se explicar el cdigo a medida que se vaya presentando. A continuacin se muestra el cdigo LINQ para Objetos:

Si se compila y ejecuta este cdigo, la salida sera:HolaLinqCarroMundoComo puede evidenciarse a partir de los resultados, se ha filtrado un listado de palabras para seleccionar slo aquellas cuya longitud sea igual o menor a cinco caracteres.Se poda argumentar que el mismo resultado podra ser logrado sin el uso de LINQ con el cdigo que se muestra a continuacin:

Observe que el "cdigo antiguo" es mucho ms corto que la versin LINQ y muy fcil de leer. Bien, no se rinda an. Hay mucho ms de LINQ que lo mostrado en este primer ejemplo sencillo.Ahora se mejorar el ejemplo con agrupamiento y ordenamiento. Esto debera dar una idea sobre por qu LINQ es til y poderoso.Para la consulta siguiente, se espera obtener el resultado siguiente:Palabras de longitud 11MaravillosoPalabras de longitud 5CarroMundoPalabras de longitud 4HolaLinqSe puede usar el siguiente cdigo C# mostrado en el listado siguiente:

En los ejemplos anteriores se ha expresado en una consulta (o ms exactamente en dos consultas anidadas) lo que podra formularse como "palabras de un listado ordenadas alfabticamente y agrupadas por su longitud en orden descendente".Como ejercicio, se le invita a que trate de escribir el mismo cdigo sin usar LINQ. Si se toma el tiempo para hacerlo, ver que toma ms cdigo y requiere manejar muchas colecciones. Una de las primeras ventajas de LINQ que resalta de este ejemplo es la expresividad que habilita: se puede expresar declarativamente lo que se desea lograr usando consultas en lugar de escribir complicados fragmentos de cdigo.Si est familiarizado con SQL, probablemente ya tiene una buena idea de lo que el cdigo est haciendo. Adems de todas estas consultas similares a SQL, LINQ tambin proporciona varias otras funciones tales comoSum,Min,Max,Averagey muchas ms que permiten realizar un rico conjunto de operaciones.Por ejemplo, aqu se suma la cantidad de cada orden en una lista de rdenes para calcular la cantidad total:decimal cantidadTotal = orders.Sum(order => order.Amount);2. LINQ para XML: consultando documentos XML.La extensibilidad de la arquitectura de consultas de LINQ es usada para proporcionar implementaciones que trabajan sobre datos XML y SQL.LINQ para XML aprovecha el marco de trabajo de LINQ para ofrecer consultas XML y transforma capacidades integradas en el lenguaje de programacin .NET anfitrin. Tambin puede pensar en LINQ para XML como una API XML con todas las funciones comparable al System.Xml .NET 2.0 rediseado y modernizado, ms algunas caractersticas de XPath y XSLT. LINQ para XML proporciona facilidades para editar documentos XML y elementos de rboles en memoria, as como facilidades de flujo. Esto significa que ser capaz de usar LINQ para XML con el propsito de desarrollar ms fcilmente muchas de las tareas de procesamiento de XML que ha estado desarrollando con las API XML tradicionales del espacio de nombres System.Xml.Primero se examinar por qu es necesaria una API XML como LINQ para XML comparndola con otras alternativas. Luego se efectuarn los primeros pasos con un poco de cdigo usando LINQ para XML en un ejemplo sencillo.2.1. Por qu se necesita LINQ para XML?Hoy en da, XML es omnipresente, y es usado extensivamente en aplicaciones escritas usando lenguajes de propsito general tales como C# o VB .NET. Es usado para intercambiar datos entre aplicaciones, almacenar informacin de configuracin, persistir datos temporales, generar pginas o reportes web, y hacer muchas otras cosas.Hasta ahora, XML no ha sido soportado de forma nativa por la mayora de lenguajes de programacin, por lo cual se requiere el uso de APIs para manejar datos XML. Estas APIs incluan XmlDocument, XmlReader, XPathNavigator, XslTransform for XSLT, SAX e implementaciones XQuery. El problema es que estas APIs no estn bien integradas con los lenguajes de programacin, requiriendo a menudo de varias lneas de cdigo complejo innecesario para lograr un simple resultado.LINQ para XML extiende la caracterstica de consulta de lenguaje integrado ofrecida por LINQ para agregar soporte para XML. Ofrece el poder expresivo de XPath y XQuery pero en C# o VB .NET, con la seguridad de tipo e IntelliSense.Si ha trabajado con documentos XML con .NET, probablemente usa XML DOM (Document Object Model) disponible en el espacio de nombres System.Xml. LINQ para XML supera la experiencia con el DOM para mejorar el conjunto de herramientas del desarrollador y evitar las limitaciones del DOM.La tabla siguiente compara las caractersticas de LINQ para XML con las de XML DOM.Caractersticas de LINQ para XMLCaractersticas de XML DOM

Centrado en elemento.Centrado en documento.

Modelo declarativo.Modelo imperativo.

El cdigo de LINQ para XML presenta una distribucin similar a la estructura jerrquica de un documento XML.Sin similitudes entre el cdigo y la estructura del documento.

Consultas integradas al lenguaje.Sin integracin de consultas.

La creacin de elementos y atributos puede ser realizada en una instruccin; los nodos de texto slo son cadenas.Las cosas bsicas requieren mucho cdigo.

Soporte de espacio de nombre XML simplificado.Requiere el tratamiento con prefijos y "administradores de espacio de nombres".

Ms rpido y ms pequeo.Pesado y de uso intensivo de memoria.

Capacidades de flujo.Todo es cargado en memoria.

APIs de simetra en elementos y atributos.Diferentes maneras de trabajar con varios fragmentos de documentos XML.

Mientras el DOM es de bajo nivel y requiere mucho cdigo para formular adecuadamente lo que se desea lograr, LINQ para XML proporciona una sintaxis de alto nivel que permite realizar cosas sencillas de manera fcil.LINQ para XML tambin permite un enfoque centrado en elemento, en comparacin con el enfoque centrado en documento de DOM. Esto significa que puede trabajar fcilmente con fragmentos XML (elementos y atributos) sin tener que crear un documento XML completo.Dos clases que .NET Framework ofrece son XmlReader y XmlWriter. Estas clases proporcionan soporte para trabajar con texto XML en su forma original y son de ms bajo nivel que LINQ para XML. LINQ para XML usa las clases XmlReader y XmlWriter de manera subyacente y no es una API XML completamente nueva. Una ventaja de esto es que permite que LINQ para XML permanezca compatible con XmlReader y XmlWriter.LINQ para XML hace ms directa la creacin de documentos, pero tambin hace ms fcil consultar documentos XML. Expresar consultas sobre documentos XML se siente ms natural que tener que escribir mucho cdigo con varios ciclos de instrucciones. Tambin, siendo parte de la familia de tecnologas LINQ, es una buena decisin cuando se necesita unir diversidad de orgenes de datos.Con LINQ para XML, Microsoft est apuntando al 80% de los casos de uso. Esos casos involucran formatos XML directos y procesamiento comn. Para el resto de los casos, los desarrolladores continuarn usando las otras APIs. Tambin, a pesar que LINQ para XML toma inspiracin de XSLT, XPath y XQuery, esas tecnologas tienen beneficios por s mismas y estn diseadas para casos de uso especficos, y dentro de esos alcances LINQ para XML no es capaz en ninguna forma de competir con ellos. LINQ para XML no es suficiente para algunos casos especficos, pero su compatibilidad con otras APIs XML permiten usarlo en combinacin con esas APIs.2.2. Cdigo LINQ para XML.El ejemplo siguiente trabaja con libros. Para este caso particular, se desea filtrar y guardar un conjunto de objetos Book como XML. As debera ser definida la clase Book en C#:

Supongamos que ahora tenemos la siguiente coleccin de libro

Usando LINQ para XML, esto puede ser hecho con el cdigo siguiente:

En contraste, el cdigo siguiente muestra cmo se debera construir el mismo documento sin LINQ para XML, usando XML DOM:

Como puede apreciarse, LINQ para XML es ms visual que el DOM. La estructura del cdigo para obtener el fragmento XML es cercano al documento que se desea producir. Se podra decir que es un cdigo WYSIWYM: lo que se mira es lo que se desea expresar (What You See Is What You Mean).Microsoft llama a este enfoque el patrn deConstruccin Funcional. Permite estructurar cdigo de forma tal que refleja la forma de un documento XML (o un fragmento) que se est construyendo.3. LINQ para SQL: Consultando bases de datos relacionales.La ambicin de LINQ es hacer de las consultas una parte natural del lenguaje de programacin. LINQ para SQL, que hizo su aparicin como DLinq, aplica este concepto para permitir a los desarrolladores consultar bases de datos relacionales usando la misma sintaxis que ha visto en LINQ para Objetos y LINQ para XML.3.1. Vista previa de las caractersticas de LINQ para SQL.LINQ para SQL proporciona acceso a datos integrado al lenguaje usando mecanismos de extensin de LINQ. Se construye sobre ADO .NET para mapear tablas y filas a clases y objetos.LINQ para SQL usa informacin de mapeado codifica en los atributos personalizados de .NET o contenidos en un documento XML. Esta informacin es usada para manejar automticamente la persistencia de objetos en bases de datos relacionales. Una tabla puede ser mapeada a una clase y las columnas de una tabla a las propiedades de la clase, y las relaciones entre tablas pueden ser representadas por propiedades adicionales.LINQ para SQL automticamente mantiene registro de los cambios a objetos y actualiza la base de datos consecuentemente por medio de consultas dinmicas SQL o procedimientos almacenados. Esta es la razn por la cual no es necesario proporcionar las consultas SQL por nosotros la mayora de las veces.3.2. LINQ para SQL.El siguiente cdigo filtra una coleccin de contactos en memoria en base a la ciudad.

Esta consulta trabaja sobre una lista de contactos de una base de datos. Observe cun sutil es la differencia entre las dos consultas. Slo el objeto sobre el cual se est trabajando es diferente; la sintaxis de la consulta es exactamente la misma. Esto muestra cmo se podr trabajar de la misma forma con mltiples tipos de datos.Usted sabe que el lenguaje de datos que una base de datos relacional entiende es SQL, y sospecha que la consulta LINQ debera ser trasladada a SQL en el mismo punto. Este es el corazn de la tecnologa: en el primer ejemplo, la coleccin es iterada en memoria, mientras que en el segundo cdigo, la consulta es usada para generar una consulta SQL que es enviada al servidor de base de datos. En el caso de consultas LINQ para SQL, el procesamiento real sucede en el servidor de base de datos. Lo sorprendente de estas consultas es que se tiene una consulta API fuertemente tipeada, en contraste con SQL, donde las consultas son expresadas en cadenas y no validadas en tiempo de compilacin.Clases entidad.El primer paso en construir una aplicacin LINQ para SQL es declarar las clases que se usarn para representar los datos de la aplicacin: las entidades.En el ejemplo sencillo, se definir una clase llamadaContacty asociada con la tablaContactsde la base de datos de muestraNorthwindproporcionada por Microsoft. Para hacer esto slo se aplica un atributo personalizado a la clase:

El atributoTablees proporcionado por LINQ para SQL en el espacio de nombres System.Data.Linq.Mapping. Tiene una propiedadNameque es usada para especificar el nombre de la base de datos.Adems de asociar las clases entidad con las tablas, es necesario definir cada campo o propiedad que se pretende asociar con una columna en la tabla. Esto se hace con el atributoColumn:

El atributoColumntambin es parte del espacio de nombres System.Data.Linq.Mapping. Tiene una variedad de propiedades que se pueden usar para personalizar el mapeo exacto entre los campos o propiedades y las columnas de la base de datos. Puede ver que se ha usado la propiedadIsPrimaryKeypara decirle a LINQ que la columna de la tabla llamadaContactIDes parte de la llave primaria de la tabla. Observe cmo se indica que la columnaContactNameser mapeada al campoName. No se especifican los nombres de las dems columnas o de los tipos de las columnas: en nuestro caso, LINQ para SQL las deducir de los campos a partir de la clase.El DataContext.Lo siguiente que se necesita preparar antes de poder usar las consultas integradas al lenguaje es un objeto System.Data.Linq.DataContext. El propsito delDataContextes traducir las solicitudes de los objetos en consultas SQL hechas sobre la base de datos y luego ensamblar objetos a partir de los resultados.Como se mencion antes, se usar la base de datos Northwnd.mdf proporcionada por Microsoft. La creacin del objetoDataContextse realiza de la manera siguiente:

El constructor de la claseDataContexttoma una cadena de conexin como parmetro. ElDataContextproporciona acceso a las tablas en la base de datos. Aqu es como se obtiene acceso a la tablaContractsmapeada a la claseContact:

DataContext.GetTable es un mtodo genrico que permite trabajar con objetos fuertemente tipeados. Esto es lo que permitir usar una consulta LINQ.A continuacin se presenta el cdigo completo del ejemplo:

Aqu est la consulta SQL que fue enviada al servidor de forma transparente:

Observe lo fcil que es obtener acceso fuertemente tipeado a una base de datos gracias a LINQ. Este es un ejemplo simplista, pero da una buena idea de lo que LINQ para SQL tiene que ofrecer y cmo podra ser cambiada la forma de trabajar con bases de datos.A continuacin se muestra un resumen de lo que LINQ para SQL ha hecho automticamente: Abrir una conexin a la base de datos. Generar la consulta SQL. Ejecutar la consulta SQL sobre la base de datos. Crear y llenar los objetos a partir de los resultados tabulares.Como ejercicio, puede intentar hacer lo mismo sin LINQ para SQL. Por ejemplo, puede tratar de usar un DataReader. Observar las siguientes caractersticas del cdigo antiguo cuando se compara con el cdigo LINQ para SQL: Consultas SQL escritas explcitamente entre comillas. No hay revisin en tiempo de compilacin. Parmetros dbilmente relacionados. Conjunto de resultados tipeados dbilmente relacionados. Se requiere ms cdigo. Se requiere ms conocimiento.Escribir cdigo estndar de acceso de acceso a datos dificulta la productividad para cada caso sencillo. En contraste, LINQ para SQL permite escribir cdigo de acceso a datos que no se interpone en el camino.3.3. Una revisin ms detallada a LINQ para SQL.Se ha visto que LINQ para SQL es capaz de generar consultas SQL dinmicas basadas en consultas integradas al lenguaje. Esto no se adapta para cada situacin, por lo que LINQ para SQL tambin soporta consultas SQL personalizadas y procedimientos almacenados, por lo que podemos usar nuestro cdigo escrito por nosotros mismos y an beneficiarnos de la infraestructura LINQ para SQL.En el ejemplo se proporcion informacin de mapeo usando atributos personalizados en las clases; pero si se prefiere no tener este tipo de informacin fuertemente codificada, es libre de usar un archivo XML externo mapeado para hacer lo mismo.Para obtener un mejor entendimiento de cmo LINQ para SQL trabaja, se crearon las entidades de clases y se proporcion la informacin de mapeo. En la prctica, este cdigo tpicamente sera generado por las herramientas que vienen con LINQ para SQL o usando el diseador grfico de LINQ para SQL.La lista de caractersticas de LINQ para SQL es mucho ms larga que esto e incluye cosas como un soporte para enlace de datos, interoperabilidad con ADO .NET, administracin de la concurrencia, soporte para herencia, y ayuda para depuracin.5.3. Desarrollando un mantenimiento de datos con LINQUnidad V - Acceso a datos con LINQ.5.3. - Desarrollando un mantenimiento de datos con LINQ.Objetivo General.Usar la herramienta de acceso a datos de LINQ en conjunto con el lenguaje de desarrollo para hacer consultas directas a la base de datos y la administracin centralizda de datos.Objetivo Especfico.Crear un mantenimiento de datos usando los patrones de LINQ.

1. Iniciando con LINQ para SQL.LINQ para SQL permite reducir la carga de red y el procesamiento del cliente, tomando ventaja de los ndices de las bases de datos.Se tomar como ejemplo la consulta a una tabla llamadabookspara consultar los libros que cuestan menos de $30 y aruparlos por tema. Para hacer esto, se pueden separar los procesos en varias tareas: seleccionar los temas ordenados, seleccionar el correspondiente filtro sobre el precio, combinar los temas con los libros, y proyectar slo los resultados que se necesitan. Se iniciar con las tareas relacionadas a los libros y luego se tratar la unin con los temas.

En este punto an se requiere solicitar toda la base de datos y filtrarlo en el cliente. Para probar esto, a continuacin se presenta la sentencia SQL enviada a la base de datos:

An se estn recuperando todos los campos de la base de datos, a pesar de que solamente se usarn dos de ellos. Adicionalmente, se estn recuperando todos los registros de la base de datos, no slo los que cumplen el criterio. Adems, tampoco se estn aprovechando los ndices debido a que se ordenan los resultados en el cliente. Idealmente, se debera definir una sentencia similar a la siguiente:

Cuntos cambios se necesitan para acomodar la consulta? Ninguno! Todo lo que se necesita es modificar la claseBooky cambiar cmo se accede a ella. Revisemos el objetoBooky la tabla para ver qu cambios sern necesarios.

Para empezar, se aplicar un mapeado de campos entre la tabla y el objeto destino. Despus se ver la unin de esta tabla con los temas correspondientes y se ver cmo se manejan las relaciones de llaves forneas en la base de datos. Por ahora, se limitar el alcance a una sola tabla. Empecemos mirando el cdigo de la claseBook, tal como se muestra a continuacin:

El cdigo anterior utiliza propiedades autoimplementadas. En este punto an se necesita una manera de llenar los objetos con datos provenientes de la base de datos. Se hace esto configurando una serie de mapeos para especificar cmo los objetos se relacionan con las tablas y columnas de la base de datos.1.1. Estableciendo el mapeo de objetos.Empecemos la exploracin de LINQ para SQL habilitando la claseBook. Para iniciar, agregar una referencia al ensambladoSystem.Data.Linq, el cual es parte del Framework .NET 3.5, y agregue una sentenciausingen la parte superior de la clase. El espacio de nombresMappingcontiene atributos que nos permiten establecer declarativamente las relaciones entre la base de datos y los objetos.using System.Data.Linq.Mapping;Se usarn atributos para declarar los mapeos de datos. En la mayora de los casos se necesita identificar dos cosas en una clase: con qu tablas est relacionado y a cules columnas estn mapeados los valores. El mapear la tablabookcon el objeto es quizs el mapeo ms sencillo. En este caso, la base de datos tiene una tabla llamadabook, por lo que se tiene un mapeo uno a uno entre ambos objetos, y tienen el mismo nombre. Para declarar el mapeado, se agrega un atributo a la declaracin de clase llamadoTable, como se muestra:

Si se desea ser ms explcito, se puede declarar el nombre de la tabla origen usando un parmetro con nombre,Name, como se muestra:

Ahora que se ha mapeado la clase a la tabla, se necesita indicar cules propiedades son almacenadas como columnas en la tabla y cmo las columnas mapean hacia la informacin de las propiedades. Se hace esto agregando un atributoColumna las propiedades que se desea mapear. Por ejemplo, para mapear la propiedadTitlea la columnaTitlede la tablaBook, se agrega un atributoColumnantes de la declaracin de propiedad:

No estamos limitados a los mapeos directos. Podemos especificar alguna traduccin entre el nombre de la columna de tabla y el nombre de la propiedad del objeto. Por ejemplo, la tablaBooktiene una columna llamadaPubDate. Para hacerle el trabajo ms fcil al desarrollador de la aplicacin cliente que trabaja con el objeto de negocios, sera deseable usar una convencin de nombres ms clara y nombrar a la propiedad comoPublicationDate. Para hacer esto, se especifica el nombre de la columna origen como parte de los parmetros del atributo.

Una cosa que debemos identificar para cada objeto es la llave primaria. En nuestro caso ser la propiedadBookId. Aqu, combinamos el parmetroNamecon un nuevo parmetroIsPrimaryKeypara declarar el mapeado. LINQ para SQL requiere que al menos una propiedad de cada objeto sea especificada como llave primaria para administrar la identidad del objeto.

Usamos el mismo mtodo para declarar los mapeados para cada una de las propiedades en nuestra clase. La declaracin resultante se muestra a continuacin.

A pesar que pueda parecer que se ha duplicado el nmero de lneas de cdigo en la claseBook, el resultado total reducir drsticamente el cdigo, ya que no necesitaremos preocuparnos sobre la creacin de mtodos separados para los mtodos Create, Read, Update y Delete (CRUD). Adicionalmente, no necesitaremos una implementacin personalizada para operaciones de consultas especializadas. Declaramos el mapeado una vez y el marco de trabajo se ocupa del resto.A pesar que se ha especificado cmo acceder a las tablas y columnas, no podemos hacer nada a menos que identifiquemos la base de datos donde residen las tablas. Necesitamos configurar nuestra conexin a la base de datos. Hacemos esto usando el nuevo objetoDataContextubicado en el espacio de nombresSystem.Data.Linq. Una vez hecho, pasamos justo a consultar los datos.1.2. Configurando el DataContext.ElDataContextmostrado yace como el corazn de LINQ para SQL y maneja la mayora del trabajo. Primero y ms importante, maneja nuestra conexin a la base de datos. Le instruimos alDataContextsobre la cadena de conexin. ElDataContextmanejar la apertura y cierre de la conexin por nosotros. Como resultado, no necesitamos preocuparnos sobre el abuso de cada conexin hacia recursos externos.

Para empezar a trabajar con elDataContext, cree una instancia de un objetoDataContextenvindole la cadena de conexin para la base de datos.

ElDataContexttambin maneja nuestros mapeados y proporciona un recurso vital - la habilidad para llenar una coleccin de objetos desde una base de datos. Llena el objeto dentro de un tipo de coleccin genrica especializada llamadaTable. Para obtener una tabla debooksdesde el objetoDataContext, se llama adataContext.GetTable():

Sin LINQ para SQL, cuando se devuelve una lista de objetos, el tipo de retorno sera unListgenrico. En este caso, estamos devolviendo un nuevo tipo -Table. Al hacer este cambio, no devolvemos los datos en bruto, sino los medios por los cuales podemos acceder y manipular dinmicamente los datos. Esto nos permitir modificar la consulta antes de enviar la solicitud a la base de datos. Ahora que tenemos acceso a los datos, veamos lo que podemos hacer con LINQ para SQL ms all de esto.2. Leyendo daos con LINQ para SQL.Lo primero que necesitamos hacer es seleccionar los valores de la base de datos. Ya hemos visto una manera de acceder a los datos usando el mtodoGetTable. La clase genricaTableimplementa una nueva interfaceIQueryable, la cual se extiende aIEnumerable. Debido a que se extiende aIQueryable, tenemos libertad para usar los operadores de consulta estndar de LINQ para Objetos. Empecemos con una consulta bsica que recupere todos los libros desde nuestro nuevo objeto refactorizado.

Con este ejemplo, hemos eliminado efectivamente cualquier cdigo ADO .NET personalizado que de otra forma habramos necesitado escribir. Sin embargo, recuperando todos los campos sin importar si los necesitamos usar.Como hemos aprendido las capacidades de LINQ para SQL, quisiramos examinar nuestro cdigo en la base de datos. En ocasiones, la consulta resultante puede ser sorprendente. Tenemos varias opciones para ver la consulta que es enviada hacia la base de datos. Usando la herramienta SQL Server Profiler que viene con SQL Server, podemos ver las sentencias mientras estn siendo enviadas hacia la base de datos. Alternativamente, podemos anexar la propiedadLogdelDataContextpara un flujo de salida, como el que tieneConsole:

Con esta funcin de registro habilitada, cualquier sentencia SQL enviada hacia la base dedatos ser enviada hacia el flujo de salida. Si lo anexamos a la consola en una aplicacin de consola, las sentencias aparecern en la ventana de consola. En una aplicacin de formularios Windows, los resultados sern enviados a la ventanaOutput. Usaremos el registro frecuentemente, para ver qu est sucediendo detrs del escenario.Como otra alternativa, Microsoft tiene una herramienta QueryVisualizer que puede ser descargada separadamente de Visual Studio 2008. La herramienta, junto con el cdigo fuente y las instrucciones de instalacin, est disponible enhttp://weblogs.asp.net/scottgu/archive/2007/07/31/linq-to-sql-debug-visualizer.aspx.Una vez esta herramienta se encuentra instalada, se puede revisar el cdigo y revisar los objetos de consulta instanciados para ver una nueva lupa como parte de la asistencia de depuracin, como se muestra en la figura siguiente:

Haga clic sobre la lupa, y se abre la ventana mostrada a continuacin, permitiendo el acceso a toda la sentencia SQL que serpa enviada. El visualizador tambin nos permite ver los resultados en una grilla de datos, y opcionalmente editar manualmente el cdigo SQL generado.Tambin podemos acceder programticamente la consulta usando el mtodoGetCommanddelDataContext, como se muestra:

Este comando no identificar cundo la consulta es ejecutada, pero mostrar la sentencia que ser enviada. Mientras se acostumbra a LINQ para SQL, pruebe cada una de estas tcnicas para ver cules trabajan mejor para usted. Sin importar cul seleccione, asegrese de observar las sentencias que estn siendo enviadas. Mientras aprende LINQ para SQL, encontrar la necesidad de alternar consultas para evitar resultados inesperados que de otra forma no podra evitar.Devolvamos la atencin a nuestra consulta. En los ejemplos previos, se mostr cmo podamos usar los mapeados para obtener valores, pero en lugar de obtener slo los campos que necesitamos, obtenemosla tabla bookcompleta. Debido a que LINQ para SQL construye sobre expresiones de consulta, podemos proyectar las columnas que deseamos en el conjunto de resultados. As, si slo queremos obtener un listado de ttulos de nuestra consulta, podramos cambiar la clusulaselectcomo se muestra a continuacin:

Debido a que usamosdataContext.Log, podemos ver en la ventanaOutputla consulta resultante.

Al revisar esta sentencia SQL, vemos que ya no estamos devolviendo todas las propiedades debookdesde nuestra base de datos. Casi hemos logrado la primera etapa: recuperar los ttulos y precios de los libros. Para lograr esta meta, necesitamos cambiar la clusulaselectpara devolver un tipo annimo con slo los valoresTitleyPrice.

Observe que el cdigo SQL generado selecciona solamente los campos solicitados como parte de la extensin del mtodoSelect, en lugar de llenar todo el objetobook.

Intente de nuevo el ejemplo, pero esta vez recorra el cdigo. Ponga atencin a la ventana de consola. Observe que el cdigo SQL no es insertado en la ventana cuando se llama al mtododataContext.GetTable(), ni es mostrada cuando se declara al objetoquery. De hecho, el SQL no es generado y enviado hacia la base de datos hasta que primero se cree el acceso a los datos. La variablequerycontiene la definicin sobre cmo deseamos acceder los datos, no los mismos datos. La ejecucin de la consulta es diferida hasta que sea usada por primera vez.Debido a que no se crea la consulta hasta que los resultados hayan sido solicitados por primera vez, podemos continuar construyendo la consulta agregando ms funcionalidades. Agregando funciones de paginado a la consulta despus que es definida por primera vez usando los mtodos de extensinSkipyTake. LINQ para SQL une entonces para crear una sola sentencia optimizada.

El cdigo resultante es el siguiente:

LINQ para Objetos estndar habra emitido una sola sentencia SELECT que recuperara todos los registros enbooks. Debido a que LINQ para SQL fue lo suficientemente listo para detectar las operaciones adicionales, fue capaz de optimizar la consulta para ser especfica a nuestra base de datos (SQL Server 2005). Si estuviramos usando SQL Server 2000, una sintaxis diferente habra sido usada porque la opcinROW_NUMBERno est disponible antes de SQL Server 2005.Hemos visto un poco de la potencia que LINQ para SQL proporciona a la tabla. En lugar de una recuperacin masiva de registros y apoyarse en LINQ para Objetos para realizar las pesada carga, LINQ para SQL tiene la potencia de evaluar nuestras solicitudes y devolver slo los resultados solicitados. Si deseamos hacer operaciones de seleccin adicionales incluyendo filtrado y ordenamiento, usamos la sintaxis de consulta SQL comn. La expresin de consulta declarativa es convertida y ajustada segn se requiera para satisfacer las necesidades del momento. Devolvamos nuestra atencin sobre la extensin de las consultas bsicas de recuperacin para agregar ms funcionalidades.3. Refinando las consultas.Hasta ahora nos hemos enfocado en recuperar los resultados de una tabla. Se ha mostrado cmo LINQ es mejor que ADO .NET porque no necesita reescribir todo el cdigo de plomera repetitivo. LINQ para SQL tambin es capaz de reducir el trfico de red al devolver slo los campos que necesitamos.Las bases de datos relacionales ofrecen capacidades especializadas para acceder y manipular conjuntos de datos asociados. Al balancear el indexado y la ejecucin de planes, la base de datos proporciona un acceso de datos ms rpido de lo que podramos tener sin los ndices. Adicionalmente, al procesar la consulta en el servidor, a menudo podemos limitar la cantidad de informacin que debe ser transmitida sobre la red. El reducir la demanda de red es importante porque el canal de red es tpicamente uno de los mayores cuellos de botella de aplicaciones centradas en datos. Continuemos nuestra revisin de LINQ para ver cmo podemos refinar nuestras consultas usando algunos procesos del lado del servidor adicionales.3.1. Filtrado.LINQ para SQL soporta un amplio rango de funcionalidades de filtrado. Un filtrado puede ser tan simple como encontrar un registro con un valor especfico. En nuestro ejemplo, queremos ver los libros que cuestan menos de 30 dlares. Podemos lograr esto con el cdigo siguiente:

Si vemos el cdigo SQL generado, el resultado es justo el esperado:

Una consulta basada en objeto recuperar todos los registros de la base de datos. Cuando se usa LINQ para SQL, podemos traducir la clusula de filtrado en una consulta parametrizada que es ejecutada en el servidor, limitando los resultados de los registros que cumplen el criterio.Adicionalmente, al usar consultas parametrizadas, solucionamos un par de asuntos comunes. Primero, una de las ms grandes vulnerabilidades de seguridad es la habilidad de inyectar funcionalidad dentro de una consulta (como borrar una tabla). Una de las maneras ms sencillas para impedir este tipo de vulnerabilidad, llamadaataque de SQL inyectado, es usar consultas parametrizadas o procedimientos almacenados.Otra ventaja de usar consultas parametrizadas es el hecho que podemos aprovechar el alojamiento en memoria del plan de consulta de SQL Server. Al reutilizar consultas donde el nico cambio son los parmetros de entrada, SQL Server puede determinar un plan de ejecucin adecuado y alojarlo en memoria para su uso posterior. En solicitudes siguientes, el servidor usar el plan de ejecucin en memoria, en lugar de reevaluar la expresin. Si se concatena la solicitud SQL, el servidor necesitara convertir la expresin cada vez para determinar el plan de ejecucin ms eficiente basado en los ndices disponibles.Algunas opciones SQL de filtrado no tienen una traduccin directa a palabras reservadas en el .NET Framework. En muchos casos, hay una alternativa que realiza lo mismo o una funcin similar. Cuando puede, LINQ traducir la llamada de funcin a su equivalente SQL.Consideremos la clusula SQLLIKE.LIKEencuentra registros basados en un esquem de coincidencia de patrones. En su lugar, el tipoStringtiene tres mtodos que realizan la misma funcin -StartsWith,EndsWithyContains. LINQ para SQL ha sido diseado para mapear esas funciones a la expresinLIKEusando el mtodosqlMethods.Likee inserta el comodn que coincide con el patrn, segn sea necesario. As, para encontrar todos los libros conteniendo la cadena "on", usamos la expresin LINQ mostrada a continuacin:

La consulta usando el mtodoContainstraduce hacia la expresin SQL siguiente:

Observe que el mtodoContainsha sido traducido aLIKEy el valor del parmetro ahora incluye el comodn %, el cual es especfico de SQL Server.No todas las funciones CLR pueden ser traducidas a un equivalente de bases de datos. Considere la consulta siguiente:

En este ejemplo, el proveedor de traducciones es capaz de convertir el mtodoDateTime.Parsee inserta una representacin especfica de base de datos para la fecha. No es capaz de manejar el mtodoToStringpara dar formato a los datos en la clusulaselect. El identificar todas las expresiones soportadas y no soportadas que son traducidas es imposible. Adicionalmente, el soporte de traduccin depende del proveedor. Cuando no est seguro si un mtodo es soportado, intntelo y vea si funciona.En muchos casos, el filtrado trabaja como se espera. En otros casos, la experimentacin es necesaria para encontrar los mtodos apropiados. No se puede cubrir todo el mapeado aqu, pero tenemos suficiente para iniciar. Al permitir que el filtro sea aplicado en el servidor en lugar de en el cliente, podemos reducir enormemente la cantidad de ancho de banda de red y aprovechar los ndices de la base de datos.Hasta ahora, hemos sido capaces de reescribir la consulta original y los objetos para devolver slo los campos deseados y los registros de la base de datos mientras eliminamos el cdigo ADO .NET. Continuemos refinando la consulta agregando ordenamiento.3.2. Ordenamiento y agrupamiento.Si necesitamos efectuar algunas funciones de ordenamiento manualmente, necesitaramos escribir mucho cdigo personalizado. LINQ para Objetos nos permite simplificar la consulta, pero para utilizar verdaderamente la potencia de la base de datos, necesitamos usar los ndices que la base de datos ha definido. La expresin de consultaorderbyyorderby...descendingestn diseadas para traducir nuestra expresin de ordenamiento hacia la base de datos. Considere el cambio que hicimos a nuestra consulta agregando la funcin de ordenamiento, tal como se muestra:

Como se indic antes, esta consulta es un verdadero ejemplo de WYWIWYM (Lo que se mira es lo que se desea expresar - What You See Is What You Mean). Como se ha visto en la cadena de consulta resultante, ahora hemos logrado otra parte de nuestra meta - balancear los ndices de la base de datos para manejar ordenamiento en lugar de ordenar del lado del cliente.

Si quisiramos ordenar los resultados en orden descendente, usaramos la expresin de consultadescendingcomo parte de la clusula. Adems, si se desea ordenar sobre varias columnas, incluiramos la lista de campos separados por comas tal como lo haramos con una expresin SQL estndar.A menudo, en lugar de slo ordenar los resultados, necesitamos agrupar los resultados. En el cdigo siguiente, agrupamos la lista de libros por tema. Proyectamos los resultados de la operacin de agrupamiento en un resultado temporal que luego podemos reutilizar.

El objeto resultante es una coleccin ordenada de colecciones. Para ver los resultados, necesitamos iterar sobre ambos resultados: los agrupamientos y la coleccin de libros contenida para cada grupo de temas. Esto producir la salida SQL siguiente:

Observe que esta consulta slo selecciona los valores llave. Como iteramos sobre resultados, consultas separadas son emitidas para cada grupo. La coleccin resultante es contenida en el objetogroupedBooks. Mientras tenemos nuestros resultados agrupados, sera bueno si pudiramos desarrollar alguna agregacin sobre los valores para que podamos ver conteos, promedios y totales por grupo.3.3. Agregacin.LINQ para SQL soporta totalmente todos los mtodos estndar de agregacin que extiendeIEnumerable. As, podemos crear una consulta para mostrar el nmero de libros que pertenecen a cada categora. El cdigo siguiente usa un tipo annimo de nuestra clusulaselectpara tomar nuestra coleccin de libros y devolver la cuenta de los libros por tema.

Observe que en este ejemplo, podramos devolver todos los libros mientras iteramos sobre el conjunto de resultados y luego contarlos en el cliente. LINQ para SQL ofrece el beneficio adicional de desarrollar la cuenta en el servidor y devolver slo el valor en lugar de sobrecargar la red con datos innecesarios. Aqu est la sentencia SQL correspondiente para esta consulta:

Continuamos con la tradicin de devolver slo los resultados que deseamos y no sobrecargar nuestra base de datos o la red con datos innecesarios.El usar los otros mtodos agregados tambin es fcil. El cdigo siguiente agrega el precio total, el precio ms bajo, el precio ms alto, y el precio promedio de los libros agrupados por tema.

Una vez ms, los mtodos de agregacin son traducidos hacia el SQL apropiado y la agregacin es desarrollada en la misma base de datos. La base de datos devuelve slo los resultados que le solicitamos, limitando la cantidad de datos que necesitamos devolver.Hasta ahora se ha trabajado slo con valores de una sola tabla. Sera bueno si se pudiera unir la tablaBookcon la tablaSubjectcorrespondiente, de forma que pudieramos incluir el nombre descriptivo del tema en lugar de un identificador crptico nico contenido en la tablaBook. Naturalmente, LINQ para SQL ofrece varias opciones para unir los resultados.3.4. Unin.El combinar datos de mltiples tablas es el corazn y alma de las bases de datos relacionales. Si no necesitramos combinar diferentes partes de datos, seramos felices escribiendo aplicaciones empresariales en Excel o en archivos de texto planos. Al ser capaces de relacionar datos, somos capaces de profundizar en informacin que de otra forma estara oculta en regiones individuales.En nuestro caso, vamos a unir la tablaBookscon la tablaSubjects. De esta manera, podemos mostrar el nombre del tema en lugar de slo la llave fornea.LINQ para SQL soporta dos sintaxis para unir. La primera usa una comparacin en la clusulaWhere, la cual es similar a la sintaxis SQL ANSI-89. Para usar esta sintaxis, podemos obtener una referencia a los objetos de tablaBookySubject. Observe que no se dijo que bamos a recuperar las tablas. Con las referencias a los objetos tabla, el cdigo siguiente muestra cmo podemos componer nuestra expresin de consulta seleccionando de ambas tablas, dondeSibjectIddel objetoSubjectes lo mismo queSubjectIDdel correspondiente objetoBook.

Hace ms de 15 aos, el estndar ANSI-92 reemplazo al estndar ANSI-89. Volver hacia la antigua sintaxis ANSI-89 puede parecer inusual. Afortunadamente, LINQ tambin soporta la sintaxisjoindel estndar SQL ANSI-92. La expresin de consulta anterior puede ser reescrita de la manera siguiente:

Tenga en cuenta que el orden de los objetos origen y destino es importante en las clusulas de unin LINQ. A diferencia de la naturaleza permisiva de SQL interpretado por la base de datos, LINQ es menos permisivo. Debido a que las expresiones de consulta son traducidas a mtodos, cambiar el orden de las tablas pero no los campos resultar en un error en tiempo de compilacin. Aqu est la definicin para la extensin del mtodoSystem.Enumerable.Linq.Join.

Observe cmo el primer y tercer parmetro coinciden, as como el segundo y el cuarto. El bloque de cdigo siguiente muestra cmo la clusulaJoinen nuestra consulta mapea hacia los parmetros del mtodo de extensin. Podemos ver cmo los parmetrosouteryouterKeySelectorcoinciden. Si furamos a transponer los parmetrosoutereinnero los correspondientesinnerKeySelectoryouterKeySelector, terminaramos con un desajuste en nuestros parmetros cuando los traducimos hacia el mtodo de extensin subyacente.

Hasta ahora, cada una de estas uniones han sido una unin cruzada (cross join) o una unin interna (inner join), donde solamente devolvemos los valores que tienen resultados similares en ambas tablas. Pero, a menudo deseamos devolver resultados de una tabla sin importar si hay resultados coincidentes en la otra tabla. En trminos de SQL estndar, esto es referido tpicamente como una unin externa (outer join). En el ejemplo anterior, se desea obtener un listado de todos los temas sin importar si existe algn libro para dicho tema. Esto tpicamente sera expresado con la siguiente expresin SQL ANSI-92:

Para lograr lo mismo con LINQ, necesitamos observar que estamos buscando libros donde existe el tema o es nulo. El mtodo de extensinDefaultIfEmpty()viene a nuestro rescate, como se muestra a continuacin:

En este caso, le decimos a LINQ que queremos unir los libros con los temas y colocar los resultados en un nuevo objeto temporal llamadojoinedBooks. Luego queremos ver los resultados de la unin deSubjectsyBooks, usando el mtodo de extensinDefaultIfEmptypara devolver un valor por defecto si el tema no contiene un libro.Ahora que podemos combinar los libros con los temas, volvamos a la consulta original que iniciamos al principio de este material para ver cunto hemos avanzado. A continuacin se muestra el resultado final.

Comparando esta consulta, podemos ver que el nico cambio real es el origen de datos. La consulta LINQ es idntica. Pero una mirada rpida en la sentencia SQL generada muestra que ahora se han recuperado slo las filas y columnas que deseamos. Adicionalmente, estamos ejecutando la unin, filtrado y ordenamiento en el servidor. Aqu est el SQL que es generado desde nuestra consulta LINQ para SQL:

La expresin LINQ es ms explcita que la sentencia SQL correspondiente debido al hecho que LINQ est diseado para trabajar no slo con datos relacionales, sino adems con otros orgenes de datos tambin, incluyendo orgenes de objetos y jerrquicos. Ya que hemos logrado nuestra meta, podramos fcilmente detenernos aqu, pero LINQ para SQL ofrece ms funcionalidades de lo que hemos visto.A pesar que hay ocasiones donde es necesario forzar una construccin relacional dentro de un modelo orientado a objetos, el trabajar directamente con jerarqua de objetos puede a menudo ser ms apropiado para el desarrollo de aplicaciones.4. Trabajando con rboles de objetos.En el corazn del desajuste de impedancia objeto-relacional est el choque entre filas de datos unidos por columnas de identificacin (relacional) y construcciones de memoria conteniendo colecciones de objetos (orientadas a objetos). Esos objetos pueden contener colecciones adicionales de objetos. As, donde nuestra base de datos contiene filas de libros y temas que podamos unir, no tiene una forma fcil para leer un tema y luego mostrar automticamente los libros asociados con ese tema. Necesitamos explcitamente decirle a la base de datos que una las dos tablas para devolver los resultados.En un mundo tpicamente orientado a objetos, podemos profundizar para identificar los libros que pertenecen a un tema. LINQ para SQL ofrece una forma fcil de navegar esas jerarquas de objetos.Si regresamos a la definicin de la claseSubject, tal vez determinemos que nos gustara un mtodo que nos permita profundizar dentro de los libros que pertenecen a ese tema. Tpicamente, haramos esocargando perezosamentelos libros relacionados a cada tema mientras los llamamos.Booksentonces sera una propiedad del objetoSubjectdonde podramos pofundizar y trabajar como quisiramos. La funcionalidad de mapeo en LINQ para SQL siguiente muestra cmo expone nuestra coleccin de objetosBookcomo un objeto genricoSystem.Data.Linq.EntitySety llamarla. De nuevo, usaremos la sintaxis de propiedad autoimplementada por brevedad.

Tal como las tablas y columnas, necesitamos decirle al framework cmo los objetos son relacionados. Haremos eso usando el atributoAssociation. Para que trabaje la asociacin, necesitamos identificar cmo nuestro tipoBookest relacionado conSubject. Asociamos los dos objetos especificando la propiedad del objeto relacionado que uniremos con nuestro objeto actual. Nuestro objetoBookcontiene una propiedadSubjectIdque ya est mapeada al campoSubjecten la tablaBooken la base de datos. As que, para la propiedad contenida enBooksde la claseSubject, especificamos que la propiedad de la claseBooksque representa la llave para nuestro registro es llamadaSubjectId. Esta llave esOtherKey, o la propiedad llave en el objeto relacionado.Ahora que hemos especificado la relacin entre los dos objetos, podemos alimentar aISubjectsusando una expresin estndar LINQ para SQL, como se muestra en el cdigo siguiente. En lugar de unir tablas especficamente, podemos profundizar directamente dentro de la coleccinbooksde cada objeto. Para mostrar los resultados, iteraremos enSubjects. Mientras recorremos dentro de cada tema, vamos a anidar un lazo que muestre los nombres de libros que estn en ese tema.

Cuando ejecutamos la consulta, podemos observar que por defecto, logramos los mismos resultados que una unin externa (outer join). Desde la perspectiva de un objeto, cuando alimentamos la lista de temas, no sabemos si tienen algunos libros asociados. Es slo cuando iteramos sobre los libros de cada tema que encontramos si hay temas sin libros asociados. Por lo que debe haber casos donde mostramos un tema que no contiene ningn libro. De igual forma, si tenemos un libro que no tiene un tema, no aparecer en el listado resultante.Para filtrar nuestros resultados un poco, tenemos a nuestra disposicin una pareja de mtodos de extensin adicionales:AnyyAll. El mtodoAnyslo devuelve resultados donde los registros relacionados existen en ambos conjuntos de resultados. Por lo que, si se desea refinar la consulta para que devuelva slo los temas que tambin tienen libros relacionados (similar a una unin interna - inner join), el cdigo siguiente usa el mtodo de extensinAny.

Si deseamos, podemos simplemente negar la clusulawherede la consulta para devolver cualquier tema donde no haya ningn libro relacionado, como se muestra:

Si deseamos filtrar los resultados y ver slo los temas donde el precio del libro es menor a 30 dlares, podemos usar el mtodo de extensinAllcomo se muestra:

La habilidad para representar nuestros datos por medio de una jerarqua de objetos ms natural nos permite trabajar con ellos en una forma de programacin ms familiar. Establecemos las dependencias de objetos basados en las necesidades especficas del negocio y podemos trabajar con ellos como lo haramos con cualquier conjunto de objetos. Esto nos permite mantener nuestras reglas de negocios e integridad sin tener que enfocarnos en la naturaleza relacional del almacn subyacente. Si deseamos, podemos reescribir nuestro ejemplo usando una sintaxis jerrquica como se muestra a continuacin:

En esta versin, no slo implementamos las jerarquas de objeto de forma ms natural(1), sino que adems anida los resultados como un conjunto similar de estructuras de objeto jerrquicas(2). De nuevo, dejamos que la base de datos haga lo que mejor sabe hacer y slo devuelve las porciones necesarias de los objetos subyacentes.Hay ocasiones donde deseamos consultar elementos que no estn relacionados. En esos casos, la unin de datos todava es requerida. Ambas opciones estn disponibles segn demanda las necesidades del negocio. Sin importar cul mtodo trabaja mejor para cada situacin, LINQ para SQL intenta devolver slo los valores solicitados y slo los devuelve cuando es necesario. Usualmente, esto es una ventaja. Ocasionalmente el comportamiento de la carga perezosa resulta en una interaccin ms frecuente con la base de datos de lo que fue la intencin originalmente. Continuemos nuestra explicacin de LINQ para SQL mirando en ocasiones donde el comportamiento por defecto puede resultar en solicitudes ms frecuentes a bases de datos.5. Cundo son cargados los datos y por qu interesa?Cuando se recuperan datos de la base de datos, LINQ para SQL utiliza una tcnica llamadacarga perezosa. Con lacarga perezosa, los resultados slo son cargados a la memoria cuando son solicitados. Revisando los ejemplos mostrados en este material y poniendo atencin a cundo las sentencias SQL son generadas, podemos ver que no son generadas cuando se define la consulta. En su lugar, la base de datos no es accedida hasta que realmente solicitemos cada registro. Esperar a acceder a los valores hasta que sean necesarios es llamadocarga perezosa.5.1. Carga perezosa.Cuando se muestran los resultados, la carga perezosa ofrece los beneficios de slo recuperar los datos cuando se soliciten, y slo devolver los datos solicitados. En muchos casos, esto proporciona beneficios de rendimiento, pero en otros casos puede conducir a algunos resultados inesperados. Considere el cdigo siguiente, el cual muestra la lista de temas que tienen o no tienen libros asociados. En este caso, enviaremos los comandos SQL generados a la ventana de consola para ser mostrados cuando la solicitud es enviada a la base de datos. Cuando ejecutamos este ejemplo, revise el cdigo y observe cuidadosamente la ventana de consola para ver exactamente cundo es emitido cada comando.

Debido a que slo queremos listar los temas, no estamos recuperando los libros. Al recuperar slo los libros si y cuando realmente los necesitamos, podemos optimizar el ancho de banda de red, minimizar el consumo de memoria, y limitar la cantidad de trabajo que la base de datos necesita hacer.Podemos extender este cdigo instruyndole aObjectDumperque no slo muestreSubjects, sino que tambin muestre sus hijos dicindole que deseamos ver cada nivel hijo adems del nivel base. El mtodoObjectDumper.Writeacepta una sobrecarga para indicar el nivel que deseamos ver. Cambie la ltima lnea para solicitar los hijos del primer nivel, como se muestra:

Observe que el registro hijo para cada tema es recuperado slo cuando se desea. Este comportamiento de carga perezosa es benfico cuando no necesitamos mostrar todos los hijos de todos los objetos padre, sino que slo deseamos recuperarlos a medida que el usuario solicita los detalles. Como solicitamos los libros de cada tema, enviaremos una consulta separada a la base de datos para cada registro de la tablaSubject. A continuacin se muestra la salida de la versin cambiada del cdigo.

En el cdigo generado, insertamos la lista de temas, luego mientras iteramos en cada elemento, emitimos una consulta separada para cada libro, pasndole la columnaiddel tema para cada registro. Esto significa que en lugar de emitir una sentencia, enviamos sentencias separadas para cada registro hijo. Antes de mejorar esta situacin, empeormosla. En este caso, copie la ltima lnea y pguela dos veces para que llamemos dos veces aObjectDumper.Write. Revisemos el cdigo y pongamos atencin al SQL que es generado.Se evitar tener que leer nuevamente los resultados. En este caso, toda la consulta fue enviada dos veces a la base de datos, una vez por cada mtodoWrite. Ahora hemos transformado una cosa muy buena (carga perezosa) en una cosa potencialmente mala (demasiado trfico de red a la base de datos). Qu podemos hacer para mejorar la situacin?5.2. Cargando detalles inmediatamente.Si todo lo que deseamos es cargar los resultados ms de una vez, podemos precargarlos y almacenarlos en un arreglo o lista usando los mtodos de extensinToList,ToDictionary,ToLookUpoToArray. As, podramos cambiar nuestra primera implementacin para indicar que deseamos cargar todos los clientes una sola vez y luego continuar con los resultados mientras la variablesubjectsest al alcance.

Al establecer explci