SlideShare una empresa de Scribd logo
LINQNovedades en VB.NET 9.0 y C# 3.0Nuevas funcionalidades en el lenguajeNuevos compiladoresNuevo IDE en Visual Studio y diseñadores gráficosSoporte para LINQ (Language Integrated Query)Manteniendo, eso sí, la compatibilidad hacia atrás, casi al 100%.Las funcionalidades añadidas asociadas a LINQ son:Sintaxis de consulta de datos.Variables implícitamente tipadas.Tipos anónimos.Inicializadores de objetos.Métodos de extensión.Expresiones Lambda.Las cuales pasaremos a ver a continuación para poder entender LINQ y su uso.
LINQVariables implícitamente tipadas:El tipo se deduce por parte del compilador y del Intellisense, en base al valor de inicialización.Fuertemente tipadas, no son generalizaciones del tipo “Variant”, pero serán del tipo más general “31/12/09” será un String.[C#]String nombre1 = “John”; // Declarada explícitamente como stringVar nombre2 = “John”;    // Implícitamente asumida como stringConsole.WriteLine(nombre2.GetType().Name); // Devuelve “String”Int edad1 = 34;	   // ExplícitamenteintegerVar edad2 = 34; 	   // Inferida como integerConsole.Writeline(edad2.GetType().Name); // Devuelve “Int32”[VB]Dim nombre1 AsString = “John”‘Explícitamente stringDim nombre2 = “John”‘Implícitamente asumida como stringConsole.WriteLine(nombre2.GetType().Name) ‘ Devuelve “String”Dim edad1 AsInteger = 34 ‘ Explícitamente integerDim edad2 = 34 ‘ Implícitamente asumida como integerConsole.Writeline(edad2.GetType().Name ‘ Devuelve “Int32”
LINQInicializadores de objetos.Nos permiten asignar valores a todos los campos y propiedades accesibles de un objeto en el momento de la creación sin tener que invocar explícitamente un constructor del mismo.List<Persona> gente = newList<Persona>();  			 [C#]Persona P = newPersona();P.Nombre = “Pepe”;P.Apellido = “Pérez”;P.Edad = 52;Gente.Add(P);// Nueva versión con inicializadoresGente.Add(newPersona{Nombre=“Pepe”,Apellido=“Pérez”,Edad=52});Dim gente AsNew List(Of Persona) 				[VB]Dim P As New personaP.Nombre = “Pepe”P.Apellido = “Pérez”P.Edad = 52Gente.Add(P)Gente.Add(New Persona With {.Nomre=“Pepe”,.Apellido=“Pérez”,.Edad=52})
LINQTipos anónimosNo es necesario declarar la clase.Se infiere el tipo de forma similar a las variables implícitamente tipadas.No dispondremos de nombre de clase, este será generado por el compilador heredando directamente de Object, por lo que no podremos referir a dicho nombre, motivo por el que son llamados anónimos.Están fuertemente tipados.No son apropiados si se ha de compartir la información con miembros o terceros, al no poder acceder al nombre de clase generado.[C#]var Empleado = new {Nombre=“JuanGómez”, Edad=33};[VB]Dim Empleado = NewWith {.Nombre=“JuanGómez”, .Edad=33}
LINQTipos anónimos (II)Antes de decidirse a crear un objeto como una instancia de una clase anónima es necesario plantearse si esta es la mejor opción en ese caso.Si se desea crear objetos temporales y no hay necesidad de otros campos o métodos, un tipo anónimo puede ser una excelente solución.También pueden ser útiles si se necesita cambiar las propiedades en cada declaración o cambiar el orden de las mismas.Pero las limitaciones inherentes a los tipos anónimos hacen que no sean viables cuando debamos compartir información, al no aparecer la clase relacionada en ningún momento en el código y, por ende, ser imposible hacer referencia a la clase o pasarla como parámetro, al no poder declarar el tipo.
LINQpublic static class DemoExtensiones {public static int CuentaPalabras(thisString Frase) {return Frase.Split(new char[] {‘ ‘, ‘,’,’.’}).Length;	}}classExtensiones {public void ExtensionesDetexto(){String FrasePrueba = “Esta es la prueba”;Console.WriteLine(FrasePrueba.CuentaPalabras());// Devuelve 4	}}Métodos de extensión en C#Estos métodos son un complemento que nos permite la ilusión de estar añadiendo nuevos métodos de clase (static) a una clase existente, sin cambiar su definición, heredarla o tener que recompilar, accediendo a ellos como si fueran métodos de instancia. Se definen como métodos static, anteponiendo “this” a primer parámetro.Se llaman mediante una instancia específica.Se asocian al tipo de dato del primer parámetro (this).
LINQImports System.Runtime.CompilerServicespublic Module UtilidadesGenerales	<Extension()> Public Function CuentaPalabras(ByVal Frase As String) As Integerreturn Frase.Split(new char() {‘ ‘, ‘,’,’.’}).Length	End FunctionEnd ModulePublic Class Extensiones public Sub ExtensionesDetexto()Dim FrasePrueba As String = “Esta es la prueba”		MsgBox(FrasePrueba.CuentaPalabras)// Devuelve 4	End SubEnd ClassMétodos de extensión en Visual BasicEstos métodos son un complemento que nos permite la ilusión de estar añadiendo nuevos procedimientos Sub o Function a una clase existente, sin cambiar su definición, heredarla o tener que recompilar. Hay que importar System.Runtime.CompilerServicesLas extensiones se definen en Modules.Hay que añadir el atributo <Extension()> al procedimiento.Se asocia al tipo del primer parámetro.
LINQUso de los métodos de extensión en LINQLos métodos de extensión más comunes son los operadores estándar de LINQ, los cuales añaden funcionalidad a los tipos ya existentes en System.Collections.Ienumerable y System.Collections.Generic.Ienumerable(T).Para usar los operadores estándar de LINQ habremos de importar la directiva System.Linq.A partir de ese momento, cualquier tipo que implemente IEnumerable(Of T) parecerá disponer de métodos de instancia como GroupBy, OrderBy, Average, etc.Se pueden ver todos estos métodos desde IntelliSense, tras pulsar el punto en una de estas instancias (Ej: List(Of T) o Array.
LINQExpresiones Lambda.Las expresiones Lambda son funciones sin nombre que calculan y devuelven un valor único y pueden ser utilizados en el mismo lugar que los tipos delegados.Pueden contener tanto expresiones como sentencias.Son el mecanismo utilizado para implementar muchas de las funciones de consulta de LINQ(Where, Select, OrderBy, …)[C#]// Buscamos números pares en una lista ya construidaNumerosPares = LosNumeros.FindAll(N => N % 2 == 0);// Frente aPublic static bool EsPar(int N) {return N % 2 == 0;}NumerosPares = LosNumeros.FindAll(new Predicate<int>(EsPar));[VB]‘Buscamos números pares en una lista ya construidaNumerosPares = LosNumeros.FindAll(Function(N As Integer) N Mod 2 = 0)‘ Frente aPublic Shared Function EsPar(ByVal N As Integer) As Boolean Return N Mod 2 = 0 End FunctionEvenNumbers = AllNumbers.FindAll(New Predicate(Of Integer) (AddressOfEsPar))
LINQExpresiones Lambda (II)
LINQ¿Qué es LINQ?Language Integrated QueryEs un conjunto de operadores de consulta que pueden utilizarse para consultar, extraer o filtrar datos.Sólo puede acceder a datos suministrados por LinqProviders, los cuales encapsulan los datos fuente como objetos accesibles por las consultas Linq.Disponible en C# 3.0 y Visual Basic .NET 9.0.Otros lenguajes tendrán soporte para Linqmás adelante.Suministra librerías de clases para el conocimiento de los datos desde el código.Lo cual nos da las ventajas de la validación de sintaxis en tiempo de compilación y desde IntelliSense.Su principal objetivo es el de la consulta de los datos referenciados, aunque algunos LinqProviders permiten la actuación sobre dichos datos para su modificación.
LINQAntes del desarrollo de LINQ, los desarrolladores teníamos que conocer el lenguaje de consulta específico para cada tipo de origen de datos.Ahora LINQnos ofrece un modelo único de trabajo sobre datos, independientemente de su origen, sólo necesitaremos dominar un lenguaje de consulta de datos para acceder a colecciones de objetos, XML, DataSets, bases de datos, … etc.Aunque un conocimiento de la técnicas subyacentes siempre será beneficioso y permitirá optimizar nuestros procesos, como ocurre con todas las tecnologías de abstracción por capas.LINQpermite consultar un limitado conjunto de datos, aquellos suministrados por los Linq Data Providers:LINQ to ObjectsLINQ to Datastes.LINQ to XML.LINQ to Entities.LINQ to SQL.LINQ Data Providers de teerceros (Line Of Business Apps, Sharepoint, …) > 100.
LINQQuery sintaxImplicity Typed VariablesAnonymous TypesObject InitializersExtension MethodsLambda Expressions
LINQRequerimientos de LINQReferencias en el proyecto:System.CoreSystem.Xml.LinqSystem.Data.LinqSystem.Data-DataSetExtensionsEspacios de nombres a importar:System.LinqSystem.Xml.LinqSystem.Data.LinqCompilación:Activar la opción de inferencia de tipos “Option Infer On”
LINQLINQ Data Providers
LINQConsultas LINQPara ejecutar una consulta LINQ se deben seguir estos tres pasos:Configurar un origen de datos.Definir la consulta.Ejecutar la consulta.‘Primer paso: Preparar datos de ejemploDim Gente As New List(Of Persona)Gente.Add(New Persona With{.Nombre=“Juan”, .Apellido=“Pérez”, .Edad=33})Gente.Add(New Persona With{.Nombre=“Pepe”, .Apellido=“Gómez”, .Edad=50})Gente.Add(New Persona With{.Nombre=“Leon”, .Apellido=“García”, .Edad=27})‘Segundo paso: Definir la consultaDim Consulta = Gente.Where(Function(P) P.Edad >= 30)‘Tercer paso: Ejecutar la consultaFor Each TreintaYTantos In ConsultaConsole.WriteLine({0} & “ “ & {1}, TreintaYTantos.Nombre, TreintaYTantos.Apellido)NextEste es un ejemplo muy sencillo, pero en el caso de otros orígenes de datos se requerirán:Dataset: necesitaremos un objeto DataSetadecuadamente rellenado con datos.Base de datos: deberemos configurar un DatContext, mediante LINQ to Entities o LINQ to SQL, que contenga una conexión a base de datos y los metadatos adecuados.Aquí simplemente se escribe una consulta utilizando los operadores de LINQ del lenguaje de nuestra elección.Habitualmente las consultas no se ejecutan en este paso, salvo que contengan funciones de agregado.Adicionalmente, esta consulta en particular hace uso de un método de extensión (Where) al que se le pasa una expresión Lambda.
LINQOpciones de sintaxis de LINQUtilizar los métodos de extensión, aunque muy potentes y con un excelente rendimiento, no redunda en la legibilidad del código, más bien le añade un nivel más de densidad.Otra opción, que generará el mismo código intermedio por parte del compilador, para el ejemplo anterior, sería:Finalmente, aquí indicamos el aspecto que tendrá el resultado de ejecutar esta consulta. Podríamos haber recuperado el objeto completo de cada elemento de la lista que cumpla la condición. Como sólo recuperamos una propiedad de tipo String, pero puede haber más de un resultado en la consulta, el tipo devuelto será una colección de String.Utilizamos una variable de tipo implícito, cuyo tipo será inferido del resultado de la consulta. En este caso, una lista de nombres, por lo que el tipo será System.Collection.Generic.IEnumerable<String>Aquí indicamos nuestro origen de datos, en este caso la colección Gente, que en el ámbito de la consulta será conocida por P, y que será del tipo Persona, inferido del contenido de la lista.Aquí filtramos los elementos a recuperar mediante el valor de una de las propiedades del tipo contenido en el origen de datos.‘ Segundo paso: Definir la consulta[C#]var TreintaYTantos = from P in Gente  where P.Edad >= 30select P.Nombre;[VB]Dim TreintaYTantos = From P In Gente _Where P.Edad >= 30 _Select P.Nombre
LINQOperadores de consulta LINQLas funciones son las mismas disponibles en SQL, aunque algún operador cambia de nombre (Take = Top)
LINQProveedores de datos – LINQ To ObjectsEs una nueva forma de trabajar con las colecciones, muy superior al tradicional bucle For Each, ya que LINQnos ofrece herramientas para filtrar, ordenar y agrupar los elementos de la lista de objetos. Adicionalmente, es más fácil leer y comprender una instrucción LINQque seguir toda la lógica del código dentro de un bucle For Each, el cual puede ser muy largo.Ventajas con respecto a los bucles For Each :Conciso y legible.Con herramientas de filtrado, ordenación y agrupación.Migrable a otras fuentes de datos sin apenas cambios.Listas IEnumerable o IEnumerable<T> consultables:List<T> / List (Of Type)ArrayDictionary(Tkey, Tvalue)
LINQProveedores de datos – LINQ To Objects[VB] Version tradicionalPrivate Class ClasificadorImplements IComparer(Of Persona) Public Function Compare(ByVal x As Persona, ByVal y As Persona) _ As Integer Implements System.Collections.Generic.IComparer _ Of Persona).Compare If x.Ciudad <> y.Ciudad Then Return New CaseInsensitiveComparer().Compare(x.Ciudad, y.Ciudad) Else Return New CaseInsensitiveComparer().Compare(x.Edad, y.Edad)       End If    End Function End Class 'Buscar a los mayores de 30, y ordenar por ciudad y edadDim Temporal As New List(Of Persona) For Each P As Persona In Gente If P.Edad >= 30 Then Temporal.Add(P) NextTemporal.Sort(New Clasificador) Nueva versionDim TempResult = From P In Gente _ Where P.Edad >= 30 _ OrderBy P.Ciudad, P.Edad _ Select P ' Pero puede tener un 25% menos rendimiento que el For Each
LINQProveedores de datos – LINQ To DatasetCon el desarrollo separado por capas, es habitual que la capa de acceso a datos devuelva directamente un DataSetcon la composición de DataTablesy sus relaciones adecuadamente cumplimentada e informada.El acceso a esta información podía ser muy fácil o muy difícil, siempre en función de  la composición del Datasety las relaciones entre las tablas que lo compongan.Ahora se ha simplificado un poco este tipo de búsquedas ya que disponemos de un proveedor de datos para LINQcontra Datasets(tipados o no tipados), el cual permite acceder a uno o más Datasetssimultáneamente, efectuar uniones entre DataTables o incluso entre DataTablesy otros tipos de datos.El acceso se efectúa al nivel DataTableen lugar de quedarse al nivel DataSet.
LINQProveedores de datos – LINQ To Dataset (II)[C#]// Rellenamos un DataSet tipadoVar DA = new dsProductsTableAdapters.ProductsTableAdapter();DA.Connection = DBConn;Var dtProductos = newdsProducts.ProductDataTable();DA.Fill(dtProductos);// Buscamos los 10 productos más carosVar MasCaros = (from P in dtProductosorderby P.ListPrice descendingselectP.Take(10);// Mostramos el resultadoForeach (var P in MasCaros)Console.WriteLine(String.Format("{0} – cuesta:{1}", P.Nombre,P.Precio));[VB]' Rellenamos un DataSet tipadoDim DA As New dsProductsTableAdapters.ProductsTableAdapterDA.Connection = DBConnDim drProductos As New dsProducts.ProductDataTableDA.Fill(dtProductos)' Buscamos los 10 productos más carosDim MasCaros = From P In dtProductos _Order By P.Precio Descending _Take 10 _Select P' Mostramos el resultadoFor Each P In masCaros   Console.WriteLine(String.Format(("{0} – cuesta:{1}", P.Nombre,P.Precio))NextEspecificamos la fuente de datos de la consulta, en este caso el DataTable antes definido sobre el DataSet, cuyo tipo devuelto será ProductRow, inferido del contenido del DataTable.Indicamos que deseamos sólo las 10 primeras filas de resultados.Declaramos una variable cuyo tipo será inferido del resultado de la consulta, en este caso será una colección enumerable del tipo ProductRowUtilizamos el operador OrderBy para especificar la ordenación deseada de los datos resultantes.Se especifica que la consulta debe devolver el objeto ProductRow completo para cada fila del conjunto de resultados.
LINQAcceso a datos con LINQEsta herramienta tan potente nos permite acceder a datos almacenados mediante los siguientes orígenes de datos, adicionales a los ya revisados.LINQ to XMLLINQ to EntitiesLINQ to SQL
LINQLINQ to XMLNo es ningún secreto que XMLes una metodología de implementación de archivos de texto de una forma estructurada que no puede ser dejada de lado por ningún desarrollador, ni ahora ni en un futuro próximo.Su implantación universal obliga a conocer y manipular adecuadamente este formato, por lo que .NET Framework 3.5 nos suministra nuevas herramientas para ello.Nueva API XML(XElement, XAttribute, XNamespace, etc)Proveedor de datos para LINQ.Los beneficios del uso de este estándar son:Es mejor y menos pesado que DOM.Es más fácil trabajar con este formato.Disponemos de validación en tiempo de compilación e InteliSense.Mejor soporte para depuración.Se puede cargar o serializar XMLdesde archivos o streams.Se puede crear y manipular árboles XMLen memoria.Es comparable a XPATH, XSLT(W3C) y XQueryen funcionalidad.
LINQLINQ to XML(II) – Creación de árboles XMLBasándonos en los nuevos tipos de datos XMLpodemos crear fácilmente árboles XML:Desde código.Desde archivos de texto, TextReadero direcciones Web.Mediante un XmlReader(Xnode.ReadFrom)XML Generado:<?xml version="1.0" encoding="utf-8"?><Email Prioridad="Alta">     <Destinatario>pepito@ibis.es</Destinatario>     <Asunto>Ejemplo XML – nueva version</Asunto>   <Cuerpo>          <Linea 1>Mas facil de usar</Linea 1>          <Linea 2>Potente y productivo</Linea 2>     </Cuerpo></Email>[C#]XElement Example1 = newXElement("Email",    newXAttribute("Prioridad", "Alta"),    newXElement("Destintario", "pepito@ibis.es"),    newXElement("Asunto", "Ejemplo XML – nueva version"),    newXElement("Cuerpo",       newXElement("Linea 1", "Mas facil de usar"),       newXElement("Linea 2", "Potente y productivo"))); [VB]Dim Example1 AsNew XElement("Email", _   New XAttribute("Prioridad", "Alta"), _   New XElement("Destinatario", "pepito@ibis.es "), _   New XElement("Asunto", "Ejemplo XML – nueva version "), _   New XElement("Cuerpo", _      New XElement("Linea 1", "Mas facil de usar "), _      New XElement("Linea 2", "Potente y productivo ")))
LINQLINQ to XML(III) – Literales XML en Visual BasicPermiten teclear (o pegar) texto XMLdirectamente en el código, ya que tiene el mismo aspecto que el XMLfinal.Tienen en cuenta los esquemas XMLaplicables.Permiten anidar código.Soportan los espacios de nombres XML.No requieren carácter de continuación de línea.Permiten el uso de IntelliSensesi hay un esquema aplicable.Dim Test = <EmailPrioridad="Alta">   <Destinatario>pepito@ibis.es</Destinatario>   <Asunto>¡Ahora <%= Now.ToShortDateString %>, VB.NET!</Asunto>   <Cuerpo>      <Linea 1>Literales XML - conciso, legible, claro</Linea 1>      <Linea 2>Muy faciles de usar, muy potentes</Linea 2>   </Cuerpo></Email>Console.WriteLine(Test.@Prioridad & " prioridad del correo a & Test.<Destinatario>.Value) Expresiones embebidasElementoAtributo
LINQLINQ to XML(IV) – ConsultasSe pueden realizar consultas sobre tipos XDocumenty XElement.Es similar, pero más rápido y fácil que XPatho XQuery.Se puede obtener el mismo resultado que con XSLT, pero con menos código y esfuerzo.File: xmltest6.xml<?xml version="1.0" encoding="utf-8"?><People>	<Person Name="John ">		<Age>33</Age>		<City>London</City>	</Person>	<Person Name="Sally ">		<Age>31</Age>		<City>London</City>	</Person>	<Person Name="Alexander ">		<Age>26</Age>		<City>London</City>	</Person>	<Person Name="Sue ">		<Age>32</Age>		<City>London</City>	</Person></People>[C#]var XMLData = XDocument.Load("c:\\code\\xmltest6.xml");var ThirtyLondon = from P in XMLData.Descendants("Person")orderby P.Element("Age").Valuewhere P.Element("City").Value == "London"selectnew {Name = P.Attribute("Name").Value,				Age = P.Element("Age").Value,				City = P.Element("City").Value};[VBDim XMLData = XDocument.Load("c:\code\xmltest6.xml")Dim ThirtyLondon = From P In XMLData.<People>.<Person> _Where P.<Age>.Value > 30 And _			    P.<City>.Value = "London" _Order By P.<Age>.Value _SelectNew With {.Name = P.@Name, _				.Age = P.<Age>.Value, _				.City = P.<City>.Value}
LINQLINQ to EntitiesEsta funcionalidad de LINQestá íntimamente ligada a ADO.NETEntityFramework, por lo que empezaremos por hablar de esta nueva funcionalidad de acceso a datos de la versión 3.5.La mayoría de nuestras aplicaciones están construidas sobre una base de datos relacional, por lo que es evidente que, de alguna forma, habrán de interactuar con dicha base de datos.La estructura de tablas de las bases de datos no siempre es óptima para su acceso desde código y el modelo conceptual suele diferir mucho del modelo físico de los datos.El EntityData Modelde ADO.NET Entity Framework es la solución a este tipo de problemas ya que se construye un modelo "lógico" de los datos, definiendo el correspondiente interfaz con el modelo físico, permitiendo el acceso desde código mediante una construcción simplificada y adecuada de los datos, con un enfoque orientado a objetos, aunque los datos subyacentes no estén en este formato.Con lo que ADO.NET nos presenta las entidades de datos como objetos en el entorno, mediante el Object Services, lo cual los hace idóneos para ser atacados desde LINQ.
LINQLINQ to Entities (II)Al ser una primera versión, está claro que, como siempre, necesitará pulirse un poco para alcanzar su pleno potencial, pero ya es una herramienta muy potente y que facilita enormemente el trabajo de desarrollo en cuanto al acceso a datos y simplifica el desarrollo de las capas de acceso a datos.LINQto Entitieses el proveedor de datos de LINQespecializado en el acceso a este tipo de origen de datos orientados a objetos, sobre el que sólo se podrán efectuar consultas y recuperación de datos, pero no modificación, al menos en esta fase temprana de implantación de la herramienta, ya que mediante EntityFrameworksí que podemos acceder a los datos en modificación.Hay dos formas de consultar datos en el EntityFramework:LINQtoEntitiesEntitySQL, utilizando comandos ADO.NET
LINQLINQ to Entities (III) Entity FrameworkUno de los objetivos de ADO.NET 3.5 es el de abstraer al desarrollador de la complejidad de los datos subyacentes y presentar un modelo conceptual de objetos (entidades).Para ello utiliza una arquitectura en 3 capas las cuales, una vez definidas las relaciones, se encargarán de gestionar automáticamente el enlace entre los objetos y los datos reales.ADO.NETEntity    .FrameworkModelo conceptual(EDM – Objetos de negocio)Mapping(Relaciona los modelos conceptual y lógico)Modelo lógico(El de la base de datos)Este modelo conceptual facilita la encapsulación de la complejidad de los datos hacia el programador y la posible evolución del esquema de la base de datos, sin afectar al código.
LINQLINQ to Entities (IV) Entity FrameworkEn muchos casos el acceso a la base de datos puede resultar más complejo de que inicialmente parecía y el nivel de conocimiento de la estructura de los mismos condiciona el código y la funcionalidad que se puede desarrollar.Tipos anónimosModelo LógicoSELECT p.FirstName, p.LastName, s.Email, s.Department FROM People p inner join Staff s on p.PersonID =  s.PersonID WHERE p.City = 'Seattle'’SELECT p.FirstName, p.LastName, c.CourseName, c.Track FROM People p inner join Staff s on p.PersonID =  s.PersonID  inner join TrainerCourses tc on s.PersonID = tc.TrainerID  inner join Courses c on tc.CourseID = c.CourseID WHERE P.City = 'Seattle' [C#]var Trainers = from T in TrainingContext.People.OfType<Trainer>() where T.City == "Seattle" selectnew   { Firstname = T.FirstName,    Lastname = T.LastName,    Courses = from C in T.Courses selectnew {CourseName = C.CourseName,    Track = C.Track}}; [VB]Dim Trainers = From T In TrainingContext.People.OfType(Of Trainer)() _ Where T.City = "Seattle" _ SelectNewWith {.Firstname = T.FirstName, _      .Lastname = T.LastName, _      .Courses = From C In T.Courses _ SelectNewWith {.CourseName = C.CourseName, _   .Track = C.Track}} Mapping[C#]var Trainers = from T in TrainingContext.People.OfType<Trainer>() where T.City == "Seattle" selectnew {Firstname = T.FirstName,    Lastname = T.LastName,     Email = T.Email,     Department = T.Department}; [VB]Dim Trainers = From T In TrainingContext.People.OfType(Of Trainer)() _ Where T.City = "Seattle" _ SelectNewWith {.Firstname = T.FirstName, _  .Lastname = T.LastName, _  .Email = T.Email, _  .Department = T.Department} Modelo Conceptual
LINQLINQ to Entities (V)La estructura del Entity FrameworkLINQ to EntitiesIEnumerable<T>Entity SQL QueryEDMObject ServicesModelo ConceptualCommand TreeEntityDataReaderEntity SQL QueryMappingEntityClient Data ProviderDBDataReaderCommand TreeModelo LógicoADO.NET Data ProvidersFuentes de datos
LINQLINQ to Entities (VI)Un vez definido nuestro modelo de entidades dispondremos de formas de consultar los datos:La tradicional, con sentencias de SQL/Transact-SQL.Utilizando consultas de Entity SQL contra el EDM.Atacar al EDM mediante LINQ toEntities.De hecho, construyen unas sobre otras, es decir, si atacamos mediante LINQ toEntities, habrá una traducción a Entity SQL por detrás, la cual, a su vez, se verá traducida a las correspondientes sentencias Transact-SQL para el acceso a los datos reales en la base de datos.Lo que desconoceremos, normalmente, es dónde se realizarán estas traducciones, ya que dependerá del soporte al modelo Entity Framework que suministre el servidor de la base de datos.
LINQLINQ to Entities (VII)Acceder al Entity Framework mediante LINQ toEntitiesLas consultas entrarán en el ámbito de un "ObjectContext".El cuál gestionará encapsulando el acceso a la capa de ObjectServices:La conexión(es) con la(s) base(s) de datos.Los metadatos de los modelos (Conceptual, mapping y lógico)La gestión del estado de los objetos (modificaciones, eliminaciones, nuevos…)Una instancia de ObjectContextse utiliza para:Acceder a los datos como objetos.Enlazar los resultados de las consultas (shape).Añadir, cambiar o eliminar objetos.Conservar los cambios en la fuente de datos.Hacer attach y detach de objetos en memoria.Serializar objetos, mediante el soporte a WCF.Gestionar las identidades de objetos y rastrear los cambios.Gestionar la concurrencia.Gestionar las conexiones.Gestionar las transacciones.
LINQLINQ to Entities (VIII)[C#]publicstaticvoid Demo1() { var TrainingContext = newTrainingEntities(); var Trainers = from T in TrainingContext.People where T.City == "Seattle" select T; foreach (var T in Trainers)       Console.WriteLine(String.Format("Name: {0} {1}", T.FirstName, 			T.LastName )); }[VB]PublicShared Sub Demo1()  Dim TrainingContext = New TrainingEntities  Dim Trainers = From T In TrainingContext.People _ Where T.City = "Seattle" _ Select T  ForEach T In Trainers       Console.WriteLine(String.Format("Name: {0} {1}",T.FirstName, _ 			T.LastName)) Next EndSub
LINQLINQ to Entities (IX) La obtención de los resultados de la consulta se difiere hasta que dichos resultados sean necesarios.Los objetos relacionados no se cargan automáticamente, como en LINQto SQL, sino que hemos de especificarlo explícitamente mediante el método Loadde las propiedades de navegación, el cual nos devolverá una EntityCollectiono EntityReference.Salvo que sepamos de antemano que un objeto relacionado será necesario, en cuyo caso puede ser "incluido" en la consulta.publicstaticvoid Demo9() { var TrainingContext = newTrainingEntities();  var Trainers = from T in TrainingContext.People.OfType<Trainer>() where T.City == "Seattle" select T; foreach (var T in Trainers) {       Console.WriteLine(String.Format("Name: {0} {1}", T.FirstName, T.LastName));       // Now explicitly load this Trainer's courses.       T.Courses.Load(); foreach (var C in T.Courses)          Console.WriteLine("   Course: " + C.CourseName);    } }Dim TrainingContext = New TrainingEntities()  Dim Trainers = From T In TrainingContext.People.OfType(Of Trainer)().Include("Courses") _ Where T.City = "Seattle" _ Select T ForEach T In Trainers    Console.WriteLine([String].Format("Name: {0} {1}", T.FirstName, T.LastName))    ForEach C In T.Courses       Console.WriteLine(" Course: " & C.CourseName) Next Next
LINQLINQ to Entities (X) – Traducción de las consultasSELECT [Project3].[CourseName] AS [CourseName] FROM ( SELECT [Extent1].[CourseName] AS [CourseName],    ( SELECT COUNT(cast(1 as bit)) AS [A1]     FROM  [dbo].[People] AS [Extent2]     LEFT OUTER JOIN      ( SELECT [Extent3].[PersonID] AS [PersonID], cast(1 as bit) AS [C1]       FROM [dbo].[Staff] AS [Extent3]     ) AS [Project1]     ON [Extent2].[PersonID] = [Project1].[PersonID]     WHERE     ( CASE WHEN       ( NOT (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL)))        THEN '2X'        ELSE '2X0X'       END LIKE '2X0X%'    )     AND     (N'Seattle' = [Extent2].[City])     AND     ( EXISTS       ( SELECT cast(1 as bit) AS [C1]         FROM         ( SELECT [TrainerCourses].[CourseID] AS [CourseID],                   [TrainerCourses].[TrainerID] AS [TrainerID]           FROM [dbo].[TrainerCourses] AS [TrainerCourses]        ) AS [Extent4]         WHERE ([Extent2].[PersonID] = [Extent4].[TrainerID])           AND ([Extent4].[CourseID] = [Extent1].[CourseID])       )    )  ) AS [C1]   FROM [dbo].[Courses] AS [Extent1]) AS [Project3] WHERE [Project3].[C1] > 1Dim CoursesInSeattle = From C In TrainingCtx.Courses _              Where (From T In TrainingCtx.People.OfType(Of Trainer)() _                  Where T.City = "Seattle" _                  And T.Courses.Any(Function(F) F.CourseID = C.CourseID) _                  Select T).Count > 1 _              Select C.CourseNameeCom.CommandText = "SELECT C " & _      "FROM TrainingEntities.Courses as C " & _      "WHERE COUNT(select VALUE Trainer.PersonID " & _         "from C.Trainer " & _         "where Trainer.City = Seattle') > 1"
LINQEntity Framework, añadir datosPara añadir datos mediante el Entity Framework deberemos:Crear un nuevo objeto del tipo adecuado.Informar todas sus propiedades, al menos las obligatorias.Ejecutar el método AddToXXX correspondiente.Salvar los cambios en el origen de datos.[C#]//Crear un ObjectContext. var TrainingCtx = new TrainingEntities();// Paso 1: Crer un objeto Trainer e informar sus propiedadesvar NewTrainer = Trainer.CreateTrainer(22, "Carol", "Smith", "Training", "csmith@contoso.com", "cs705", "Mrs");// Paso 2: Informar también las no obligatorias NewTrainer.City = "London";NewTrainer.Phone = "555-54321";// Paso 3: Añadir el Trainer a las colleccionesTrainingCtx.AddToPeople(NewTrainer);// Paso 4: Salvar los cambiosTrainingCtx.SaveChanges();[VB]'Crear un ObjectContext.Dim TrainingCtx = New TrainingEntities'Paso 1: Crer un objeto Trainer e informar sus propiedadesDim NewTrainer = Trainer.CreateTrainer(16, "Peter", "Willford", _"Training", "pwillford@contoso.com","pw706", "Mr")' Paso 2: Informar también las no obligatorias NewTrainer.City = "London"NewTrainer.Phone = "555-889767"' Paso 3: Añadir el Trainer a las colleccionesTrainingCtx.AddToPeople(NewTrainer)' Paso 4: Salvar los cambiosTrainingCtx.SaveChanges()
LINQLINQ to SQLAunque la metodología preferida será en un futuro próximo LINQ toEntities, ya que Microsoft ha comunicado que no habrá actualizaciones ni mejoras al LINQ to SQL, esta es, de momento, la metodología actual en muchas instalaciones, debido a su sencillez (relativa) y a que Entity Framework no estaba aún disponible o se considera una tecnología no lo suficientemente madura y sujeta a posibles cambios.Algunas de las características de esta tecnología son:LINQ to SQL es una implementación de acceso mediante objetos a datos almacenados de forma relacional, utilizando para ello un modelo de objetos de datos.Permite un mapeo directo contra el esquema subyacente de SQL Server.Soporta tablas, transacciones, vistas y procedimientos almacenados.Permite la selección, inserción, actualización y eliminación de datos.Lógicamente estas funcionalidades se realizan mediante la traducción simultánea en ambos sentidos.
LINQLINQ to SQL(II) – Sintaxis de consulta[C#]var TrainingCtx = new LINQtoSQL.LINQtoSQLTrainingDataContext();var People = from P in TrainingCtx.Peoplesorderby P.LastNameselect P;foreach (var P in People) {if (P.Staff != null) { Console.WriteLine("Trainer: {0} {1} Email:{2}", P.FirstName,      P.LastName, P.Staff.Email);    }else Console.WriteLine("Person: {0} {1}", P.FirstName, P.LastName);} [VB]Dim TrainingCtx = New LINQtoSQL.LINQtoSQLTrainingDataContextDim People = From P In TrainingCtx.Peoples _Order By P.LastName _Select PFor Each P In PeopleIf P.Staff IsNot Nothing Then      Console.WriteLine("Trainer: {0} {1} Email:{2}", _      P.FirstName, P.LastName, P.Staff.Email)Else      Console.WriteLine("Person: {0} {1}", P.FirstName, P.LastName)   End IfNext
LINQLINQ to SQL(III)Como en el caso de LINQ toEntities, la ejecución de las consultas se difiere hasta que los resultados sean necesarios.Aunque la carga de datos relacionados está habilitada por defecto (LazyLoading).Para desactivarla deberemos modificar las DataLoadOptionsdel objeto ObjectContext.[c#]var TrainingCtx = new LINQtoSQL.LINQtoSQLTrainingDataContext();  //Desactivar Lazy Loading  TrainingCtx.DeferredLoadingEnabled = false;  [VB]Dim TrainingCtx = New LINQtoSQL.LINQtoSQLTrain'Desactivar Lazy Loading TrainingCtx.DeferredLoadingEnabled = False
LINQLINQ to SQL(III) – Añadir datos[C#]var TrainingCtx = new LINQtoSQL.LINQtoSQLTrainingDataContext();var NewPerson = new LINQtoSQL.People();NewPerson.PersonID = 32;NewPerson.FirstName = "John";NewPerson.LastName = "Sawyer";NewPerson.City = "London";NewPerson.Phone = "555-32432";TrainingCtx.Peoples.InsertOnSubmit(NewPerson);TrainingCtx.SubmitChanges();[VB]Dim TrainingCtx = New LINQtoSQL.LINQtoSQLTrainingDataContextDim NewPerson = New LINQtoSQL.PeopleNewPerson.PersonID = 31NewPerson.FirstName = "John"NewPerson.LastName = "Sawyer"NewPerson.City = "London"NewPerson.Phone = "555-32432"TrainingCtx.Peoples.InsertOnSubmit(NewPerson)TrainingCtx.SubmitChanges()1º - Crear un nuevo objeto del tipo adecuado2º - Cumplimentar sus propiedades3º - pasar el objeto al método adecuado.4º - Salvar los cambios para que se efectúe la inserción
LINQLINQ to SQL(III) – Modificar datos[C#]var TrainingCtx = new LINQtoSQL.LINQtoSQLTrainingDataContext();var ThePerson = TrainingCtx.Peoples.Single(P => P.PersonID == 3);ThePerson.Phone = "555-33345";TrainingCtx.SubmitChanges();[VB]Dim TrainingCtx = New LINQtoSQL.LINQtoSQLTrainingDataContextDim ThePerson = _   TrainingCtx.Peoples.Single(Function(P) P.PersonID = 3)ThePerson.Phone = "555-33345"TrainingCtx.SubmitChanges()

Más contenido relacionado

PPT
Introduccion a LINQ
PPTX
Linq con visual studio 2008
PDF
Ejemplo Linq To SQL
PPTX
Programación con linq
PPTX
.Net Remoting
PPTX
Jugando con LinQ
PDF
M1 introduccion a php
Introduccion a LINQ
Linq con visual studio 2008
Ejemplo Linq To SQL
Programación con linq
.Net Remoting
Jugando con LinQ
M1 introduccion a php

Destacado (8)

PDF
Entendiendo el .NET Framework
PPTX
Linq
PPTX
LINQ for slideshare
PDF
Introduccion a Visual Studio .NET
PPT
PPT
Introduccion A Linq 1205779028184546 5
PPT
CORREOS ELECTRONICOS
PPTX
Los Correos Electronicos
Entendiendo el .NET Framework
Linq
LINQ for slideshare
Introduccion a Visual Studio .NET
Introduccion A Linq 1205779028184546 5
CORREOS ELECTRONICOS
Los Correos Electronicos
Publicidad

Similar a Framework .NET 3.5 10 Linq (20)

PPTX
Framework .NET 3.5 07 Programación orientada a objetos
PPTX
Java 8
PPTX
Framework .NET 3.5 06 Operativa básica del framework .net
PDF
Introduccion a-linq..www.freelibros.com
PDF
Functional SE.pdf
PPTX
Java 8 - Nuevas características
PPT
Rompiendo dependencias contenidas en ensamblados .NET mediante la refactoriza...
PDF
Java8 : Más allá de las Expresiones Lambdas
PPTX
13-Unidad 3: Operaciones LINQ -3.1 Introducción 3.2 LINQ SELECT 3.3 LINQ INSERT
PPTX
Conceptos-HTML-y-JavaScript-Bloque-3-JavaScript.pptx
PDF
Kit de supervivencia para Java 8 : como prepararse para Java 9
PDF
Linq to sql 6
PPTX
Portafolio parcial 2
PDF
Linq to sql 3
PPTX
Portafolio de evidencias
PDF
C# Nuevas características en C# 6
PPTX
Portafolio de evidencias
PPT
Linq 1207579553462901 8
PDF
Linq to sql 2
PPTX
Operadores poo
Framework .NET 3.5 07 Programación orientada a objetos
Java 8
Framework .NET 3.5 06 Operativa básica del framework .net
Introduccion a-linq..www.freelibros.com
Functional SE.pdf
Java 8 - Nuevas características
Rompiendo dependencias contenidas en ensamblados .NET mediante la refactoriza...
Java8 : Más allá de las Expresiones Lambdas
13-Unidad 3: Operaciones LINQ -3.1 Introducción 3.2 LINQ SELECT 3.3 LINQ INSERT
Conceptos-HTML-y-JavaScript-Bloque-3-JavaScript.pptx
Kit de supervivencia para Java 8 : como prepararse para Java 9
Linq to sql 6
Portafolio parcial 2
Linq to sql 3
Portafolio de evidencias
C# Nuevas características en C# 6
Portafolio de evidencias
Linq 1207579553462901 8
Linq to sql 2
Operadores poo
Publicidad

Más de Antonio Palomares Sender (11)

PPTX
Framework .NET 3.5 15 Configuración y despliegue de soluciones
PPTX
Framework .NET 3.5 13 Programación orientada a la red
PPTX
Framework .NET 3.5 12 Uso de system.drawing
PPTX
Framework .NET 3.5 11 Seguridad
PPTX
Framework .NET 3.5 09 Depuración, monitorización y pruebas
PPTX
Framework .NET 3.5 08 Validación de datos
PPTX
Framework .NET 3.5 05 Tipo y jerarquía de objetos
PPTX
Framework .NET 3.5 04 El common language runtime
PPTX
Framework .NET 3.5 02 Entorno de desarrollo (ide)
PPTX
Framework .NET 3.5 14 Gestión de archivos y serialización
PPTX
Framework .NET 3.5 01 Conceptos básicos y entorno
Framework .NET 3.5 15 Configuración y despliegue de soluciones
Framework .NET 3.5 13 Programación orientada a la red
Framework .NET 3.5 12 Uso de system.drawing
Framework .NET 3.5 11 Seguridad
Framework .NET 3.5 09 Depuración, monitorización y pruebas
Framework .NET 3.5 08 Validación de datos
Framework .NET 3.5 05 Tipo y jerarquía de objetos
Framework .NET 3.5 04 El common language runtime
Framework .NET 3.5 02 Entorno de desarrollo (ide)
Framework .NET 3.5 14 Gestión de archivos y serialización
Framework .NET 3.5 01 Conceptos básicos y entorno

Último (20)

PDF
5.1 Pinch y Bijker en libro Actos, actores y artefactos de Bunch Thomas (coor...
PDF
Plantilla para Diseño de Narrativas Transmedia.pdf
PDF
Estrategia de apoyo tecnología miguel angel solis
PDF
Influencia-del-uso-de-redes-sociales.pdf
DOCX
Zarate Quispe Alex aldayir aplicaciones de internet .docx
PPTX
Power Point Nicolás Carrasco (disertación Roblox).pptx
PDF
MANUAL TECNOLOGÍA SER MINISTERIO EDUCACIÓN
PDF
programa-de-estudios-2011-guc3ada-para-el-maestro-secundarias-tecnicas-tecnol...
PPTX
RAP02 - TECNICO SISTEMAS TELEINFORMATICOS.pptx
PDF
Diapositiva proyecto de vida, materia catedra
PPTX
Sesion 1 de microsoft power point - Clase 1
PDF
SAP Transportation Management para LSP, TM140 Col18
PPTX
Propuesta BKP servidores con Acronis1.pptx
PDF
MÓDULO DE CALOR DE GRADO DE MEDIO DE FORMACIÓN PROFESIONAL
PPTX
sa-cs-82-powerpoint-hardware-y-software_ver_4.pptx
PPTX
Acronis Cyber Protect Cloud para Ciber Proteccion y Ciber Seguridad LATAM - A...
PPTX
RAP01 - TECNICO SISTEMAS TELEINFORMATICOS.pptx
PPTX
ANCASH-CRITERIOS DE EVALUACIÓN-FORMA-10-10 (2).pptx
PDF
Estrategia de apoyo tecnología grado 9-3
PPTX
REDES INFORMATICAS REDES INFORMATICAS.pptx
5.1 Pinch y Bijker en libro Actos, actores y artefactos de Bunch Thomas (coor...
Plantilla para Diseño de Narrativas Transmedia.pdf
Estrategia de apoyo tecnología miguel angel solis
Influencia-del-uso-de-redes-sociales.pdf
Zarate Quispe Alex aldayir aplicaciones de internet .docx
Power Point Nicolás Carrasco (disertación Roblox).pptx
MANUAL TECNOLOGÍA SER MINISTERIO EDUCACIÓN
programa-de-estudios-2011-guc3ada-para-el-maestro-secundarias-tecnicas-tecnol...
RAP02 - TECNICO SISTEMAS TELEINFORMATICOS.pptx
Diapositiva proyecto de vida, materia catedra
Sesion 1 de microsoft power point - Clase 1
SAP Transportation Management para LSP, TM140 Col18
Propuesta BKP servidores con Acronis1.pptx
MÓDULO DE CALOR DE GRADO DE MEDIO DE FORMACIÓN PROFESIONAL
sa-cs-82-powerpoint-hardware-y-software_ver_4.pptx
Acronis Cyber Protect Cloud para Ciber Proteccion y Ciber Seguridad LATAM - A...
RAP01 - TECNICO SISTEMAS TELEINFORMATICOS.pptx
ANCASH-CRITERIOS DE EVALUACIÓN-FORMA-10-10 (2).pptx
Estrategia de apoyo tecnología grado 9-3
REDES INFORMATICAS REDES INFORMATICAS.pptx

Framework .NET 3.5 10 Linq

  • 1. LINQNovedades en VB.NET 9.0 y C# 3.0Nuevas funcionalidades en el lenguajeNuevos compiladoresNuevo IDE en Visual Studio y diseñadores gráficosSoporte para LINQ (Language Integrated Query)Manteniendo, eso sí, la compatibilidad hacia atrás, casi al 100%.Las funcionalidades añadidas asociadas a LINQ son:Sintaxis de consulta de datos.Variables implícitamente tipadas.Tipos anónimos.Inicializadores de objetos.Métodos de extensión.Expresiones Lambda.Las cuales pasaremos a ver a continuación para poder entender LINQ y su uso.
  • 2. LINQVariables implícitamente tipadas:El tipo se deduce por parte del compilador y del Intellisense, en base al valor de inicialización.Fuertemente tipadas, no son generalizaciones del tipo “Variant”, pero serán del tipo más general “31/12/09” será un String.[C#]String nombre1 = “John”; // Declarada explícitamente como stringVar nombre2 = “John”; // Implícitamente asumida como stringConsole.WriteLine(nombre2.GetType().Name); // Devuelve “String”Int edad1 = 34; // ExplícitamenteintegerVar edad2 = 34; // Inferida como integerConsole.Writeline(edad2.GetType().Name); // Devuelve “Int32”[VB]Dim nombre1 AsString = “John”‘Explícitamente stringDim nombre2 = “John”‘Implícitamente asumida como stringConsole.WriteLine(nombre2.GetType().Name) ‘ Devuelve “String”Dim edad1 AsInteger = 34 ‘ Explícitamente integerDim edad2 = 34 ‘ Implícitamente asumida como integerConsole.Writeline(edad2.GetType().Name ‘ Devuelve “Int32”
  • 3. LINQInicializadores de objetos.Nos permiten asignar valores a todos los campos y propiedades accesibles de un objeto en el momento de la creación sin tener que invocar explícitamente un constructor del mismo.List<Persona> gente = newList<Persona>(); [C#]Persona P = newPersona();P.Nombre = “Pepe”;P.Apellido = “Pérez”;P.Edad = 52;Gente.Add(P);// Nueva versión con inicializadoresGente.Add(newPersona{Nombre=“Pepe”,Apellido=“Pérez”,Edad=52});Dim gente AsNew List(Of Persona) [VB]Dim P As New personaP.Nombre = “Pepe”P.Apellido = “Pérez”P.Edad = 52Gente.Add(P)Gente.Add(New Persona With {.Nomre=“Pepe”,.Apellido=“Pérez”,.Edad=52})
  • 4. LINQTipos anónimosNo es necesario declarar la clase.Se infiere el tipo de forma similar a las variables implícitamente tipadas.No dispondremos de nombre de clase, este será generado por el compilador heredando directamente de Object, por lo que no podremos referir a dicho nombre, motivo por el que son llamados anónimos.Están fuertemente tipados.No son apropiados si se ha de compartir la información con miembros o terceros, al no poder acceder al nombre de clase generado.[C#]var Empleado = new {Nombre=“JuanGómez”, Edad=33};[VB]Dim Empleado = NewWith {.Nombre=“JuanGómez”, .Edad=33}
  • 5. LINQTipos anónimos (II)Antes de decidirse a crear un objeto como una instancia de una clase anónima es necesario plantearse si esta es la mejor opción en ese caso.Si se desea crear objetos temporales y no hay necesidad de otros campos o métodos, un tipo anónimo puede ser una excelente solución.También pueden ser útiles si se necesita cambiar las propiedades en cada declaración o cambiar el orden de las mismas.Pero las limitaciones inherentes a los tipos anónimos hacen que no sean viables cuando debamos compartir información, al no aparecer la clase relacionada en ningún momento en el código y, por ende, ser imposible hacer referencia a la clase o pasarla como parámetro, al no poder declarar el tipo.
  • 6. LINQpublic static class DemoExtensiones {public static int CuentaPalabras(thisString Frase) {return Frase.Split(new char[] {‘ ‘, ‘,’,’.’}).Length; }}classExtensiones {public void ExtensionesDetexto(){String FrasePrueba = “Esta es la prueba”;Console.WriteLine(FrasePrueba.CuentaPalabras());// Devuelve 4 }}Métodos de extensión en C#Estos métodos son un complemento que nos permite la ilusión de estar añadiendo nuevos métodos de clase (static) a una clase existente, sin cambiar su definición, heredarla o tener que recompilar, accediendo a ellos como si fueran métodos de instancia. Se definen como métodos static, anteponiendo “this” a primer parámetro.Se llaman mediante una instancia específica.Se asocian al tipo de dato del primer parámetro (this).
  • 7. LINQImports System.Runtime.CompilerServicespublic Module UtilidadesGenerales <Extension()> Public Function CuentaPalabras(ByVal Frase As String) As Integerreturn Frase.Split(new char() {‘ ‘, ‘,’,’.’}).Length End FunctionEnd ModulePublic Class Extensiones public Sub ExtensionesDetexto()Dim FrasePrueba As String = “Esta es la prueba” MsgBox(FrasePrueba.CuentaPalabras)// Devuelve 4 End SubEnd ClassMétodos de extensión en Visual BasicEstos métodos son un complemento que nos permite la ilusión de estar añadiendo nuevos procedimientos Sub o Function a una clase existente, sin cambiar su definición, heredarla o tener que recompilar. Hay que importar System.Runtime.CompilerServicesLas extensiones se definen en Modules.Hay que añadir el atributo <Extension()> al procedimiento.Se asocia al tipo del primer parámetro.
  • 8. LINQUso de los métodos de extensión en LINQLos métodos de extensión más comunes son los operadores estándar de LINQ, los cuales añaden funcionalidad a los tipos ya existentes en System.Collections.Ienumerable y System.Collections.Generic.Ienumerable(T).Para usar los operadores estándar de LINQ habremos de importar la directiva System.Linq.A partir de ese momento, cualquier tipo que implemente IEnumerable(Of T) parecerá disponer de métodos de instancia como GroupBy, OrderBy, Average, etc.Se pueden ver todos estos métodos desde IntelliSense, tras pulsar el punto en una de estas instancias (Ej: List(Of T) o Array.
  • 9. LINQExpresiones Lambda.Las expresiones Lambda son funciones sin nombre que calculan y devuelven un valor único y pueden ser utilizados en el mismo lugar que los tipos delegados.Pueden contener tanto expresiones como sentencias.Son el mecanismo utilizado para implementar muchas de las funciones de consulta de LINQ(Where, Select, OrderBy, …)[C#]// Buscamos números pares en una lista ya construidaNumerosPares = LosNumeros.FindAll(N => N % 2 == 0);// Frente aPublic static bool EsPar(int N) {return N % 2 == 0;}NumerosPares = LosNumeros.FindAll(new Predicate<int>(EsPar));[VB]‘Buscamos números pares en una lista ya construidaNumerosPares = LosNumeros.FindAll(Function(N As Integer) N Mod 2 = 0)‘ Frente aPublic Shared Function EsPar(ByVal N As Integer) As Boolean Return N Mod 2 = 0 End FunctionEvenNumbers = AllNumbers.FindAll(New Predicate(Of Integer) (AddressOfEsPar))
  • 11. LINQ¿Qué es LINQ?Language Integrated QueryEs un conjunto de operadores de consulta que pueden utilizarse para consultar, extraer o filtrar datos.Sólo puede acceder a datos suministrados por LinqProviders, los cuales encapsulan los datos fuente como objetos accesibles por las consultas Linq.Disponible en C# 3.0 y Visual Basic .NET 9.0.Otros lenguajes tendrán soporte para Linqmás adelante.Suministra librerías de clases para el conocimiento de los datos desde el código.Lo cual nos da las ventajas de la validación de sintaxis en tiempo de compilación y desde IntelliSense.Su principal objetivo es el de la consulta de los datos referenciados, aunque algunos LinqProviders permiten la actuación sobre dichos datos para su modificación.
  • 12. LINQAntes del desarrollo de LINQ, los desarrolladores teníamos que conocer el lenguaje de consulta específico para cada tipo de origen de datos.Ahora LINQnos ofrece un modelo único de trabajo sobre datos, independientemente de su origen, sólo necesitaremos dominar un lenguaje de consulta de datos para acceder a colecciones de objetos, XML, DataSets, bases de datos, … etc.Aunque un conocimiento de la técnicas subyacentes siempre será beneficioso y permitirá optimizar nuestros procesos, como ocurre con todas las tecnologías de abstracción por capas.LINQpermite consultar un limitado conjunto de datos, aquellos suministrados por los Linq Data Providers:LINQ to ObjectsLINQ to Datastes.LINQ to XML.LINQ to Entities.LINQ to SQL.LINQ Data Providers de teerceros (Line Of Business Apps, Sharepoint, …) > 100.
  • 13. LINQQuery sintaxImplicity Typed VariablesAnonymous TypesObject InitializersExtension MethodsLambda Expressions
  • 14. LINQRequerimientos de LINQReferencias en el proyecto:System.CoreSystem.Xml.LinqSystem.Data.LinqSystem.Data-DataSetExtensionsEspacios de nombres a importar:System.LinqSystem.Xml.LinqSystem.Data.LinqCompilación:Activar la opción de inferencia de tipos “Option Infer On”
  • 16. LINQConsultas LINQPara ejecutar una consulta LINQ se deben seguir estos tres pasos:Configurar un origen de datos.Definir la consulta.Ejecutar la consulta.‘Primer paso: Preparar datos de ejemploDim Gente As New List(Of Persona)Gente.Add(New Persona With{.Nombre=“Juan”, .Apellido=“Pérez”, .Edad=33})Gente.Add(New Persona With{.Nombre=“Pepe”, .Apellido=“Gómez”, .Edad=50})Gente.Add(New Persona With{.Nombre=“Leon”, .Apellido=“García”, .Edad=27})‘Segundo paso: Definir la consultaDim Consulta = Gente.Where(Function(P) P.Edad >= 30)‘Tercer paso: Ejecutar la consultaFor Each TreintaYTantos In ConsultaConsole.WriteLine({0} & “ “ & {1}, TreintaYTantos.Nombre, TreintaYTantos.Apellido)NextEste es un ejemplo muy sencillo, pero en el caso de otros orígenes de datos se requerirán:Dataset: necesitaremos un objeto DataSetadecuadamente rellenado con datos.Base de datos: deberemos configurar un DatContext, mediante LINQ to Entities o LINQ to SQL, que contenga una conexión a base de datos y los metadatos adecuados.Aquí simplemente se escribe una consulta utilizando los operadores de LINQ del lenguaje de nuestra elección.Habitualmente las consultas no se ejecutan en este paso, salvo que contengan funciones de agregado.Adicionalmente, esta consulta en particular hace uso de un método de extensión (Where) al que se le pasa una expresión Lambda.
  • 17. LINQOpciones de sintaxis de LINQUtilizar los métodos de extensión, aunque muy potentes y con un excelente rendimiento, no redunda en la legibilidad del código, más bien le añade un nivel más de densidad.Otra opción, que generará el mismo código intermedio por parte del compilador, para el ejemplo anterior, sería:Finalmente, aquí indicamos el aspecto que tendrá el resultado de ejecutar esta consulta. Podríamos haber recuperado el objeto completo de cada elemento de la lista que cumpla la condición. Como sólo recuperamos una propiedad de tipo String, pero puede haber más de un resultado en la consulta, el tipo devuelto será una colección de String.Utilizamos una variable de tipo implícito, cuyo tipo será inferido del resultado de la consulta. En este caso, una lista de nombres, por lo que el tipo será System.Collection.Generic.IEnumerable<String>Aquí indicamos nuestro origen de datos, en este caso la colección Gente, que en el ámbito de la consulta será conocida por P, y que será del tipo Persona, inferido del contenido de la lista.Aquí filtramos los elementos a recuperar mediante el valor de una de las propiedades del tipo contenido en el origen de datos.‘ Segundo paso: Definir la consulta[C#]var TreintaYTantos = from P in Gente where P.Edad >= 30select P.Nombre;[VB]Dim TreintaYTantos = From P In Gente _Where P.Edad >= 30 _Select P.Nombre
  • 18. LINQOperadores de consulta LINQLas funciones son las mismas disponibles en SQL, aunque algún operador cambia de nombre (Take = Top)
  • 19. LINQProveedores de datos – LINQ To ObjectsEs una nueva forma de trabajar con las colecciones, muy superior al tradicional bucle For Each, ya que LINQnos ofrece herramientas para filtrar, ordenar y agrupar los elementos de la lista de objetos. Adicionalmente, es más fácil leer y comprender una instrucción LINQque seguir toda la lógica del código dentro de un bucle For Each, el cual puede ser muy largo.Ventajas con respecto a los bucles For Each :Conciso y legible.Con herramientas de filtrado, ordenación y agrupación.Migrable a otras fuentes de datos sin apenas cambios.Listas IEnumerable o IEnumerable<T> consultables:List<T> / List (Of Type)ArrayDictionary(Tkey, Tvalue)
  • 20. LINQProveedores de datos – LINQ To Objects[VB] Version tradicionalPrivate Class ClasificadorImplements IComparer(Of Persona) Public Function Compare(ByVal x As Persona, ByVal y As Persona) _ As Integer Implements System.Collections.Generic.IComparer _ Of Persona).Compare If x.Ciudad <> y.Ciudad Then Return New CaseInsensitiveComparer().Compare(x.Ciudad, y.Ciudad) Else Return New CaseInsensitiveComparer().Compare(x.Edad, y.Edad) End If End Function End Class 'Buscar a los mayores de 30, y ordenar por ciudad y edadDim Temporal As New List(Of Persona) For Each P As Persona In Gente If P.Edad >= 30 Then Temporal.Add(P) NextTemporal.Sort(New Clasificador) Nueva versionDim TempResult = From P In Gente _ Where P.Edad >= 30 _ OrderBy P.Ciudad, P.Edad _ Select P ' Pero puede tener un 25% menos rendimiento que el For Each
  • 21. LINQProveedores de datos – LINQ To DatasetCon el desarrollo separado por capas, es habitual que la capa de acceso a datos devuelva directamente un DataSetcon la composición de DataTablesy sus relaciones adecuadamente cumplimentada e informada.El acceso a esta información podía ser muy fácil o muy difícil, siempre en función de la composición del Datasety las relaciones entre las tablas que lo compongan.Ahora se ha simplificado un poco este tipo de búsquedas ya que disponemos de un proveedor de datos para LINQcontra Datasets(tipados o no tipados), el cual permite acceder a uno o más Datasetssimultáneamente, efectuar uniones entre DataTables o incluso entre DataTablesy otros tipos de datos.El acceso se efectúa al nivel DataTableen lugar de quedarse al nivel DataSet.
  • 22. LINQProveedores de datos – LINQ To Dataset (II)[C#]// Rellenamos un DataSet tipadoVar DA = new dsProductsTableAdapters.ProductsTableAdapter();DA.Connection = DBConn;Var dtProductos = newdsProducts.ProductDataTable();DA.Fill(dtProductos);// Buscamos los 10 productos más carosVar MasCaros = (from P in dtProductosorderby P.ListPrice descendingselectP.Take(10);// Mostramos el resultadoForeach (var P in MasCaros)Console.WriteLine(String.Format("{0} – cuesta:{1}", P.Nombre,P.Precio));[VB]' Rellenamos un DataSet tipadoDim DA As New dsProductsTableAdapters.ProductsTableAdapterDA.Connection = DBConnDim drProductos As New dsProducts.ProductDataTableDA.Fill(dtProductos)' Buscamos los 10 productos más carosDim MasCaros = From P In dtProductos _Order By P.Precio Descending _Take 10 _Select P' Mostramos el resultadoFor Each P In masCaros Console.WriteLine(String.Format(("{0} – cuesta:{1}", P.Nombre,P.Precio))NextEspecificamos la fuente de datos de la consulta, en este caso el DataTable antes definido sobre el DataSet, cuyo tipo devuelto será ProductRow, inferido del contenido del DataTable.Indicamos que deseamos sólo las 10 primeras filas de resultados.Declaramos una variable cuyo tipo será inferido del resultado de la consulta, en este caso será una colección enumerable del tipo ProductRowUtilizamos el operador OrderBy para especificar la ordenación deseada de los datos resultantes.Se especifica que la consulta debe devolver el objeto ProductRow completo para cada fila del conjunto de resultados.
  • 23. LINQAcceso a datos con LINQEsta herramienta tan potente nos permite acceder a datos almacenados mediante los siguientes orígenes de datos, adicionales a los ya revisados.LINQ to XMLLINQ to EntitiesLINQ to SQL
  • 24. LINQLINQ to XMLNo es ningún secreto que XMLes una metodología de implementación de archivos de texto de una forma estructurada que no puede ser dejada de lado por ningún desarrollador, ni ahora ni en un futuro próximo.Su implantación universal obliga a conocer y manipular adecuadamente este formato, por lo que .NET Framework 3.5 nos suministra nuevas herramientas para ello.Nueva API XML(XElement, XAttribute, XNamespace, etc)Proveedor de datos para LINQ.Los beneficios del uso de este estándar son:Es mejor y menos pesado que DOM.Es más fácil trabajar con este formato.Disponemos de validación en tiempo de compilación e InteliSense.Mejor soporte para depuración.Se puede cargar o serializar XMLdesde archivos o streams.Se puede crear y manipular árboles XMLen memoria.Es comparable a XPATH, XSLT(W3C) y XQueryen funcionalidad.
  • 25. LINQLINQ to XML(II) – Creación de árboles XMLBasándonos en los nuevos tipos de datos XMLpodemos crear fácilmente árboles XML:Desde código.Desde archivos de texto, TextReadero direcciones Web.Mediante un XmlReader(Xnode.ReadFrom)XML Generado:<?xml version="1.0" encoding="utf-8"?><Email Prioridad="Alta"> <Destinatario>pepito@ibis.es</Destinatario> <Asunto>Ejemplo XML – nueva version</Asunto> <Cuerpo> <Linea 1>Mas facil de usar</Linea 1> <Linea 2>Potente y productivo</Linea 2> </Cuerpo></Email>[C#]XElement Example1 = newXElement("Email", newXAttribute("Prioridad", "Alta"), newXElement("Destintario", "pepito@ibis.es"), newXElement("Asunto", "Ejemplo XML – nueva version"), newXElement("Cuerpo", newXElement("Linea 1", "Mas facil de usar"), newXElement("Linea 2", "Potente y productivo"))); [VB]Dim Example1 AsNew XElement("Email", _ New XAttribute("Prioridad", "Alta"), _ New XElement("Destinatario", "pepito@ibis.es "), _ New XElement("Asunto", "Ejemplo XML – nueva version "), _ New XElement("Cuerpo", _ New XElement("Linea 1", "Mas facil de usar "), _ New XElement("Linea 2", "Potente y productivo ")))
  • 26. LINQLINQ to XML(III) – Literales XML en Visual BasicPermiten teclear (o pegar) texto XMLdirectamente en el código, ya que tiene el mismo aspecto que el XMLfinal.Tienen en cuenta los esquemas XMLaplicables.Permiten anidar código.Soportan los espacios de nombres XML.No requieren carácter de continuación de línea.Permiten el uso de IntelliSensesi hay un esquema aplicable.Dim Test = <EmailPrioridad="Alta"> <Destinatario>pepito@ibis.es</Destinatario> <Asunto>¡Ahora <%= Now.ToShortDateString %>, VB.NET!</Asunto> <Cuerpo> <Linea 1>Literales XML - conciso, legible, claro</Linea 1> <Linea 2>Muy faciles de usar, muy potentes</Linea 2> </Cuerpo></Email>Console.WriteLine(Test.@Prioridad & " prioridad del correo a & Test.<Destinatario>.Value) Expresiones embebidasElementoAtributo
  • 27. LINQLINQ to XML(IV) – ConsultasSe pueden realizar consultas sobre tipos XDocumenty XElement.Es similar, pero más rápido y fácil que XPatho XQuery.Se puede obtener el mismo resultado que con XSLT, pero con menos código y esfuerzo.File: xmltest6.xml<?xml version="1.0" encoding="utf-8"?><People> <Person Name="John "> <Age>33</Age> <City>London</City> </Person> <Person Name="Sally "> <Age>31</Age> <City>London</City> </Person> <Person Name="Alexander "> <Age>26</Age> <City>London</City> </Person> <Person Name="Sue "> <Age>32</Age> <City>London</City> </Person></People>[C#]var XMLData = XDocument.Load("c:\\code\\xmltest6.xml");var ThirtyLondon = from P in XMLData.Descendants("Person")orderby P.Element("Age").Valuewhere P.Element("City").Value == "London"selectnew {Name = P.Attribute("Name").Value, Age = P.Element("Age").Value, City = P.Element("City").Value};[VBDim XMLData = XDocument.Load("c:\code\xmltest6.xml")Dim ThirtyLondon = From P In XMLData.<People>.<Person> _Where P.<Age>.Value > 30 And _ P.<City>.Value = "London" _Order By P.<Age>.Value _SelectNew With {.Name = P.@Name, _ .Age = P.<Age>.Value, _ .City = P.<City>.Value}
  • 28. LINQLINQ to EntitiesEsta funcionalidad de LINQestá íntimamente ligada a ADO.NETEntityFramework, por lo que empezaremos por hablar de esta nueva funcionalidad de acceso a datos de la versión 3.5.La mayoría de nuestras aplicaciones están construidas sobre una base de datos relacional, por lo que es evidente que, de alguna forma, habrán de interactuar con dicha base de datos.La estructura de tablas de las bases de datos no siempre es óptima para su acceso desde código y el modelo conceptual suele diferir mucho del modelo físico de los datos.El EntityData Modelde ADO.NET Entity Framework es la solución a este tipo de problemas ya que se construye un modelo "lógico" de los datos, definiendo el correspondiente interfaz con el modelo físico, permitiendo el acceso desde código mediante una construcción simplificada y adecuada de los datos, con un enfoque orientado a objetos, aunque los datos subyacentes no estén en este formato.Con lo que ADO.NET nos presenta las entidades de datos como objetos en el entorno, mediante el Object Services, lo cual los hace idóneos para ser atacados desde LINQ.
  • 29. LINQLINQ to Entities (II)Al ser una primera versión, está claro que, como siempre, necesitará pulirse un poco para alcanzar su pleno potencial, pero ya es una herramienta muy potente y que facilita enormemente el trabajo de desarrollo en cuanto al acceso a datos y simplifica el desarrollo de las capas de acceso a datos.LINQto Entitieses el proveedor de datos de LINQespecializado en el acceso a este tipo de origen de datos orientados a objetos, sobre el que sólo se podrán efectuar consultas y recuperación de datos, pero no modificación, al menos en esta fase temprana de implantación de la herramienta, ya que mediante EntityFrameworksí que podemos acceder a los datos en modificación.Hay dos formas de consultar datos en el EntityFramework:LINQtoEntitiesEntitySQL, utilizando comandos ADO.NET
  • 30. LINQLINQ to Entities (III) Entity FrameworkUno de los objetivos de ADO.NET 3.5 es el de abstraer al desarrollador de la complejidad de los datos subyacentes y presentar un modelo conceptual de objetos (entidades).Para ello utiliza una arquitectura en 3 capas las cuales, una vez definidas las relaciones, se encargarán de gestionar automáticamente el enlace entre los objetos y los datos reales.ADO.NETEntity .FrameworkModelo conceptual(EDM – Objetos de negocio)Mapping(Relaciona los modelos conceptual y lógico)Modelo lógico(El de la base de datos)Este modelo conceptual facilita la encapsulación de la complejidad de los datos hacia el programador y la posible evolución del esquema de la base de datos, sin afectar al código.
  • 31. LINQLINQ to Entities (IV) Entity FrameworkEn muchos casos el acceso a la base de datos puede resultar más complejo de que inicialmente parecía y el nivel de conocimiento de la estructura de los mismos condiciona el código y la funcionalidad que se puede desarrollar.Tipos anónimosModelo LógicoSELECT p.FirstName, p.LastName, s.Email, s.Department FROM People p inner join Staff s on p.PersonID = s.PersonID WHERE p.City = 'Seattle'’SELECT p.FirstName, p.LastName, c.CourseName, c.Track FROM People p inner join Staff s on p.PersonID = s.PersonID inner join TrainerCourses tc on s.PersonID = tc.TrainerID inner join Courses c on tc.CourseID = c.CourseID WHERE P.City = 'Seattle' [C#]var Trainers = from T in TrainingContext.People.OfType<Trainer>() where T.City == "Seattle" selectnew { Firstname = T.FirstName, Lastname = T.LastName, Courses = from C in T.Courses selectnew {CourseName = C.CourseName, Track = C.Track}}; [VB]Dim Trainers = From T In TrainingContext.People.OfType(Of Trainer)() _ Where T.City = "Seattle" _ SelectNewWith {.Firstname = T.FirstName, _ .Lastname = T.LastName, _ .Courses = From C In T.Courses _ SelectNewWith {.CourseName = C.CourseName, _ .Track = C.Track}} Mapping[C#]var Trainers = from T in TrainingContext.People.OfType<Trainer>() where T.City == "Seattle" selectnew {Firstname = T.FirstName, Lastname = T.LastName, Email = T.Email, Department = T.Department}; [VB]Dim Trainers = From T In TrainingContext.People.OfType(Of Trainer)() _ Where T.City = "Seattle" _ SelectNewWith {.Firstname = T.FirstName, _ .Lastname = T.LastName, _ .Email = T.Email, _ .Department = T.Department} Modelo Conceptual
  • 32. LINQLINQ to Entities (V)La estructura del Entity FrameworkLINQ to EntitiesIEnumerable<T>Entity SQL QueryEDMObject ServicesModelo ConceptualCommand TreeEntityDataReaderEntity SQL QueryMappingEntityClient Data ProviderDBDataReaderCommand TreeModelo LógicoADO.NET Data ProvidersFuentes de datos
  • 33. LINQLINQ to Entities (VI)Un vez definido nuestro modelo de entidades dispondremos de formas de consultar los datos:La tradicional, con sentencias de SQL/Transact-SQL.Utilizando consultas de Entity SQL contra el EDM.Atacar al EDM mediante LINQ toEntities.De hecho, construyen unas sobre otras, es decir, si atacamos mediante LINQ toEntities, habrá una traducción a Entity SQL por detrás, la cual, a su vez, se verá traducida a las correspondientes sentencias Transact-SQL para el acceso a los datos reales en la base de datos.Lo que desconoceremos, normalmente, es dónde se realizarán estas traducciones, ya que dependerá del soporte al modelo Entity Framework que suministre el servidor de la base de datos.
  • 34. LINQLINQ to Entities (VII)Acceder al Entity Framework mediante LINQ toEntitiesLas consultas entrarán en el ámbito de un "ObjectContext".El cuál gestionará encapsulando el acceso a la capa de ObjectServices:La conexión(es) con la(s) base(s) de datos.Los metadatos de los modelos (Conceptual, mapping y lógico)La gestión del estado de los objetos (modificaciones, eliminaciones, nuevos…)Una instancia de ObjectContextse utiliza para:Acceder a los datos como objetos.Enlazar los resultados de las consultas (shape).Añadir, cambiar o eliminar objetos.Conservar los cambios en la fuente de datos.Hacer attach y detach de objetos en memoria.Serializar objetos, mediante el soporte a WCF.Gestionar las identidades de objetos y rastrear los cambios.Gestionar la concurrencia.Gestionar las conexiones.Gestionar las transacciones.
  • 35. LINQLINQ to Entities (VIII)[C#]publicstaticvoid Demo1() { var TrainingContext = newTrainingEntities(); var Trainers = from T in TrainingContext.People where T.City == "Seattle" select T; foreach (var T in Trainers) Console.WriteLine(String.Format("Name: {0} {1}", T.FirstName, T.LastName )); }[VB]PublicShared Sub Demo1() Dim TrainingContext = New TrainingEntities Dim Trainers = From T In TrainingContext.People _ Where T.City = "Seattle" _ Select T ForEach T In Trainers Console.WriteLine(String.Format("Name: {0} {1}",T.FirstName, _ T.LastName)) Next EndSub
  • 36. LINQLINQ to Entities (IX) La obtención de los resultados de la consulta se difiere hasta que dichos resultados sean necesarios.Los objetos relacionados no se cargan automáticamente, como en LINQto SQL, sino que hemos de especificarlo explícitamente mediante el método Loadde las propiedades de navegación, el cual nos devolverá una EntityCollectiono EntityReference.Salvo que sepamos de antemano que un objeto relacionado será necesario, en cuyo caso puede ser "incluido" en la consulta.publicstaticvoid Demo9() { var TrainingContext = newTrainingEntities(); var Trainers = from T in TrainingContext.People.OfType<Trainer>() where T.City == "Seattle" select T; foreach (var T in Trainers) { Console.WriteLine(String.Format("Name: {0} {1}", T.FirstName, T.LastName)); // Now explicitly load this Trainer's courses. T.Courses.Load(); foreach (var C in T.Courses) Console.WriteLine(" Course: " + C.CourseName); } }Dim TrainingContext = New TrainingEntities() Dim Trainers = From T In TrainingContext.People.OfType(Of Trainer)().Include("Courses") _ Where T.City = "Seattle" _ Select T ForEach T In Trainers Console.WriteLine([String].Format("Name: {0} {1}", T.FirstName, T.LastName)) ForEach C In T.Courses Console.WriteLine(" Course: " & C.CourseName) Next Next
  • 37. LINQLINQ to Entities (X) – Traducción de las consultasSELECT [Project3].[CourseName] AS [CourseName] FROM ( SELECT [Extent1].[CourseName] AS [CourseName], ( SELECT COUNT(cast(1 as bit)) AS [A1] FROM [dbo].[People] AS [Extent2] LEFT OUTER JOIN ( SELECT [Extent3].[PersonID] AS [PersonID], cast(1 as bit) AS [C1] FROM [dbo].[Staff] AS [Extent3] ) AS [Project1] ON [Extent2].[PersonID] = [Project1].[PersonID] WHERE ( CASE WHEN ( NOT (([Project1].[C1] = 1) AND ([Project1].[C1] IS NOT NULL))) THEN '2X' ELSE '2X0X' END LIKE '2X0X%' ) AND (N'Seattle' = [Extent2].[City]) AND ( EXISTS ( SELECT cast(1 as bit) AS [C1] FROM ( SELECT [TrainerCourses].[CourseID] AS [CourseID], [TrainerCourses].[TrainerID] AS [TrainerID] FROM [dbo].[TrainerCourses] AS [TrainerCourses] ) AS [Extent4] WHERE ([Extent2].[PersonID] = [Extent4].[TrainerID]) AND ([Extent4].[CourseID] = [Extent1].[CourseID]) ) ) ) AS [C1] FROM [dbo].[Courses] AS [Extent1]) AS [Project3] WHERE [Project3].[C1] > 1Dim CoursesInSeattle = From C In TrainingCtx.Courses _ Where (From T In TrainingCtx.People.OfType(Of Trainer)() _ Where T.City = "Seattle" _ And T.Courses.Any(Function(F) F.CourseID = C.CourseID) _ Select T).Count > 1 _ Select C.CourseNameeCom.CommandText = "SELECT C " & _ "FROM TrainingEntities.Courses as C " & _ "WHERE COUNT(select VALUE Trainer.PersonID " & _ "from C.Trainer " & _ "where Trainer.City = Seattle') > 1"
  • 38. LINQEntity Framework, añadir datosPara añadir datos mediante el Entity Framework deberemos:Crear un nuevo objeto del tipo adecuado.Informar todas sus propiedades, al menos las obligatorias.Ejecutar el método AddToXXX correspondiente.Salvar los cambios en el origen de datos.[C#]//Crear un ObjectContext. var TrainingCtx = new TrainingEntities();// Paso 1: Crer un objeto Trainer e informar sus propiedadesvar NewTrainer = Trainer.CreateTrainer(22, "Carol", "Smith", "Training", "csmith@contoso.com", "cs705", "Mrs");// Paso 2: Informar también las no obligatorias NewTrainer.City = "London";NewTrainer.Phone = "555-54321";// Paso 3: Añadir el Trainer a las colleccionesTrainingCtx.AddToPeople(NewTrainer);// Paso 4: Salvar los cambiosTrainingCtx.SaveChanges();[VB]'Crear un ObjectContext.Dim TrainingCtx = New TrainingEntities'Paso 1: Crer un objeto Trainer e informar sus propiedadesDim NewTrainer = Trainer.CreateTrainer(16, "Peter", "Willford", _"Training", "pwillford@contoso.com","pw706", "Mr")' Paso 2: Informar también las no obligatorias NewTrainer.City = "London"NewTrainer.Phone = "555-889767"' Paso 3: Añadir el Trainer a las colleccionesTrainingCtx.AddToPeople(NewTrainer)' Paso 4: Salvar los cambiosTrainingCtx.SaveChanges()
  • 39. LINQLINQ to SQLAunque la metodología preferida será en un futuro próximo LINQ toEntities, ya que Microsoft ha comunicado que no habrá actualizaciones ni mejoras al LINQ to SQL, esta es, de momento, la metodología actual en muchas instalaciones, debido a su sencillez (relativa) y a que Entity Framework no estaba aún disponible o se considera una tecnología no lo suficientemente madura y sujeta a posibles cambios.Algunas de las características de esta tecnología son:LINQ to SQL es una implementación de acceso mediante objetos a datos almacenados de forma relacional, utilizando para ello un modelo de objetos de datos.Permite un mapeo directo contra el esquema subyacente de SQL Server.Soporta tablas, transacciones, vistas y procedimientos almacenados.Permite la selección, inserción, actualización y eliminación de datos.Lógicamente estas funcionalidades se realizan mediante la traducción simultánea en ambos sentidos.
  • 40. LINQLINQ to SQL(II) – Sintaxis de consulta[C#]var TrainingCtx = new LINQtoSQL.LINQtoSQLTrainingDataContext();var People = from P in TrainingCtx.Peoplesorderby P.LastNameselect P;foreach (var P in People) {if (P.Staff != null) { Console.WriteLine("Trainer: {0} {1} Email:{2}", P.FirstName, P.LastName, P.Staff.Email); }else Console.WriteLine("Person: {0} {1}", P.FirstName, P.LastName);} [VB]Dim TrainingCtx = New LINQtoSQL.LINQtoSQLTrainingDataContextDim People = From P In TrainingCtx.Peoples _Order By P.LastName _Select PFor Each P In PeopleIf P.Staff IsNot Nothing Then Console.WriteLine("Trainer: {0} {1} Email:{2}", _ P.FirstName, P.LastName, P.Staff.Email)Else Console.WriteLine("Person: {0} {1}", P.FirstName, P.LastName) End IfNext
  • 41. LINQLINQ to SQL(III)Como en el caso de LINQ toEntities, la ejecución de las consultas se difiere hasta que los resultados sean necesarios.Aunque la carga de datos relacionados está habilitada por defecto (LazyLoading).Para desactivarla deberemos modificar las DataLoadOptionsdel objeto ObjectContext.[c#]var TrainingCtx = new LINQtoSQL.LINQtoSQLTrainingDataContext(); //Desactivar Lazy Loading TrainingCtx.DeferredLoadingEnabled = false; [VB]Dim TrainingCtx = New LINQtoSQL.LINQtoSQLTrain'Desactivar Lazy Loading TrainingCtx.DeferredLoadingEnabled = False
  • 42. LINQLINQ to SQL(III) – Añadir datos[C#]var TrainingCtx = new LINQtoSQL.LINQtoSQLTrainingDataContext();var NewPerson = new LINQtoSQL.People();NewPerson.PersonID = 32;NewPerson.FirstName = "John";NewPerson.LastName = "Sawyer";NewPerson.City = "London";NewPerson.Phone = "555-32432";TrainingCtx.Peoples.InsertOnSubmit(NewPerson);TrainingCtx.SubmitChanges();[VB]Dim TrainingCtx = New LINQtoSQL.LINQtoSQLTrainingDataContextDim NewPerson = New LINQtoSQL.PeopleNewPerson.PersonID = 31NewPerson.FirstName = "John"NewPerson.LastName = "Sawyer"NewPerson.City = "London"NewPerson.Phone = "555-32432"TrainingCtx.Peoples.InsertOnSubmit(NewPerson)TrainingCtx.SubmitChanges()1º - Crear un nuevo objeto del tipo adecuado2º - Cumplimentar sus propiedades3º - pasar el objeto al método adecuado.4º - Salvar los cambios para que se efectúe la inserción
  • 43. LINQLINQ to SQL(III) – Modificar datos[C#]var TrainingCtx = new LINQtoSQL.LINQtoSQLTrainingDataContext();var ThePerson = TrainingCtx.Peoples.Single(P => P.PersonID == 3);ThePerson.Phone = "555-33345";TrainingCtx.SubmitChanges();[VB]Dim TrainingCtx = New LINQtoSQL.LINQtoSQLTrainingDataContextDim ThePerson = _ TrainingCtx.Peoples.Single(Function(P) P.PersonID = 3)ThePerson.Phone = "555-33345"TrainingCtx.SubmitChanges()