Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa | ||
|
fw:othersnet:linq [2009/03/23 07:56] alfred |
fw:othersnet:linq [2020/05/09 09:25] (actual) |
||
|---|---|---|---|
| Línea 1: | Línea 1: | ||
| ====== LINQ ====== | ====== LINQ ====== | ||
| + | ===== Sintaxis ===== | ||
| - | En System.Linq existen una serie de métodos de extensión que permiten hacer consultas sobre datos (sobre xml, bases de datos...). | + | En ''System.Linq'' existen una serie de métodos de extensión que permiten hacer consultas sobre datos (sobre xml, bases de datos...). \\ \\ |
| Los siguientes son ejemplos de consultas sobre elementos en memoria: | Los siguientes son ejemplos de consultas sobre elementos en memoria: | ||
| + | <code csharp> | ||
| IEnumerable<Person> list = lPerson.Where(p => p.firstName.StartsWith("A")); | IEnumerable<Person> list = lPerson.Where(p => p.firstName.StartsWith("A")); | ||
| int maxAge = lPerson.Max(p => p.age); | int maxAge = lPerson.Max(p => p.age); | ||
| double avg = lPerson.Average(p => p.age); | double avg = lPerson.Average(p => p.age); | ||
| - | + | </code> | |
| - | Pero en LINQ existen lo que serían las sintaxis de expresiones para realizar este tipo de consultas. Estas son parecidas a las sentencias sql de toda la vida y empiezan siempre por from y acaban por select siguiendo una estructura como la que sigue: | + | Pero en LINQ existen lo que serían las sintaxis de expresiones para realizar este tipo de consultas. Estas son parecidas a las sentencias sql de toda la vida y empiezan siempre por **from** y acaban por **select** siguiendo una estructura como la que sigue: |
| + | <code csharp> | ||
| from elementos_a_consultar in lista select elementos_devueltos | from elementos_a_consultar in lista select elementos_devueltos | ||
| + | </code> | ||
| Un ejemplo: | Un ejemplo: | ||
| + | <code csharp> | ||
| IEnumerable<Person> list = from p in lPerson select p; | IEnumerable<Person> list = from p in lPerson select p; | ||
| + | </code> | ||
| + | |||
| + | ===== Filtro y ordenación ===== | ||
| También podemos agregar clausulas where y orderby: | También podemos agregar clausulas where y orderby: | ||
| + | <code csharp> | ||
| IEnumerable<Person> list = from p | IEnumerable<Person> list = from p | ||
| in lPerson | in lPerson | ||
| Línea 21: | Línea 28: | ||
| orderby p.age | orderby p.age | ||
| select p; | select p; | ||
| - | + | </code> | |
| - | En el código de arriba el trozo “from p in lPerson” indica lanzar una consulta LINQ sobre la colección “lPerson”, y que usaremos el parámetro “p” para representar a cada elemento que consultamos. En realidad, el nombre del parámetro “p” es irrelevante - podría haberlo llamado “o”, “x”, “person” o de cualquier otra forma. El trozo “select p” nos indica que queremos devolver una secuencia IEnumerable de objetos Person como resultado de la consulta. Esto esto pasa porque la colección “lPerson” contiene objetos de tipo “Person”. Pero si quisieramos devolver los nombres sería algo así: | + | En el código de arriba el trozo //from p in lPerson// indica lanzar una consulta LINQ sobre la colección ''lPerson'', y que usaremos el parámetro ''p'' para representar a cada elemento que consultamos. En realidad, el nombre del parámetro ''p'' es irrelevante - podría haberlo llamado ''o'', ''x'', ''person'' o de cualquier otra forma. El trozo //select p// nos indica que queremos devolver una secuencia IEnumerable de objetos Person como resultado de la consulta. Esto esto pasa porque la colección ''lPerson'' contiene objetos de tipo ''Person''. Pero si quisieramos devolver los nombres sería algo así: |
| + | <code csharp> | ||
| IEnumerable<string> list = from p | IEnumerable<string> list = from p | ||
| in lPerson | in lPerson | ||
| Línea 28: | Línea 36: | ||
| orderby p.age | orderby p.age | ||
| select p.firstName; | select p.firstName; | ||
| + | </code> | ||
| También podemos consultar los elementos relacionados o ordendar descendentemente: | También podemos consultar los elementos relacionados o ordendar descendentemente: | ||
| + | <code csharp> | ||
| IEnumerable<string> categories = from c in Categories | IEnumerable<string> categories = from c in Categories | ||
| where c.Products.Count > 5 | where c.Products.Count > 5 | ||
| orderby c.CategoryName descending | orderby c.CategoryName descending | ||
| select c.CategoryName; | select c.CategoryName; | ||
| + | </code> | ||
| Otro ejemplo sería el de devolver un objeto de una clase que no es la de los elementos de la lista: | Otro ejemplo sería el de devolver un objeto de una clase que no es la de los elementos de la lista: | ||
| + | <code csharp> | ||
| class AlternatePerson { | class AlternatePerson { | ||
| string nameAge { get; set; } | string nameAge { get; set; } | ||
| Línea 45: | Línea 55: | ||
| nameAge = p.FirstName + p.Age; | nameAge = p.FirstName + p.Age; | ||
| } | } | ||
| + | </code> | ||
| - | Una de las principales características de la interface IEnumerable<T> es que los objetos que las implementen pueden retrasar su ejecución hasta el momento en que se introduzca en un bucle (esto es posible gracias al “yield”). LINQ usa esta ventaja, retrasando las consultas hasta la primera vez que se itere sobre el resultado. Si nunca se itera sobre una IEnumerable<T>, entonces, la consulta nunca es ejecutada. Pero si lo que queremos es ejecutar inmediatamente la consulta (utilizando toList o toArray) haremos: | + | ===== Momento de la consulta ===== |
| + | |||
| + | Una de las principales características de la interface IEnumerable<T> es que los objetos que las implementen pueden retrasar su ejecución hasta el momento en que se introduzca en un bucle (esto es posible gracias al ''yield''). LINQ usa esta ventaja, retrasando las consultas hasta la primera vez que se itere sobre el resultado. Si nunca se itera sobre una IEnumerable<T>, entonces, la consulta nunca es ejecutada. Pero si lo que queremos es ejecutar inmediatamente la consulta (utilizando toList o toArray) haremos: | ||
| + | <code csharp> | ||
| List<Category> categories = (from c in db.Categories | List<Category> categories = (from c in db.Categories | ||
| where c.CategoryName | where c.CategoryName | ||
| select c).ToList(); | select c).ToList(); | ||
| + | </code> | ||
| Si luego cambiasemos los datos de la lista inicial y volviesemos a iterarla, se volvería a ejecutar la query. Por ejemplo, en la siguiente aparece Juanjo en la segunda iteración: | Si luego cambiasemos los datos de la lista inicial y volviesemos a iterarla, se volvería a ejecutar la query. Por ejemplo, en la siguiente aparece Juanjo en la segunda iteración: | ||
| + | <code csharp> | ||
| var list = from l in lPerson select l; | var list = from l in lPerson select l; | ||
| foreach (Person p in list) | foreach (Person p in list) | ||
| Línea 58: | Línea 73: | ||
| foreach (Person p in list) | foreach (Person p in list) | ||
| Console.WriteLine(p.firstName); | Console.WriteLine(p.firstName); | ||
| + | </code> | ||
| + | ===== Ejemplos ===== | ||
| - | Ejemplos: | + | ==== Sencillos ==== |
| - | Where + and | + | === Where + and === |
| + | <code csharp> | ||
| var expensiveInStockProducts = | var expensiveInStockProducts = | ||
| from p in products | from p in products | ||
| where p.UnitsInStock > 0 && p.UnitPrice > 3.00M | where p.UnitsInStock > 0 && p.UnitPrice > 3.00M | ||
| select p; | select p; | ||
| + | </code> | ||
| - | Buscar las palabras que tengan más letras que su valor | + | === Buscar las palabras que tengan más letras que su valor === |
| + | <code csharp> | ||
| string[] digits = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }; | string[] digits = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }; | ||
| var shortDigits = digits.Where((digit, index) => digit.Length < index); | var shortDigits = digits.Where((digit, index) => digit.Length < index); | ||
| - | + | </code> | |
| - | Cambiando el valor | + | === Cambiando el valor === |
| + | <code csharp> | ||
| int[] numbers = { 5, 4, 1}; | int[] numbers = { 5, 4, 1}; | ||
| var numsPlusOne = | var numsPlusOne = | ||
| from n in numbers | from n in numbers | ||
| select n + 1; | select n + 1; | ||
| + | </code> | ||
| Devolvería 6 5 2 | Devolvería 6 5 2 | ||
| + | === Combinar dos arrays === | ||
| + | <code csharp> | ||
| int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; | int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; | ||
| string[] strings = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }; | string[] strings = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }; | ||
| Línea 83: | Línea 106: | ||
| from n in numbers | from n in numbers | ||
| select strings[n]; | select strings[n]; | ||
| + | </code> | ||
| + | Devolvería five, four, one... | ||
| + | |||
| + | ==== Grouping ==== | ||
| - | Grouping | ||
| Coger una agrupación y el tipo de agrupación que es: | Coger una agrupación y el tipo de agrupación que es: | ||
| + | <code csharp> | ||
| var wordGroups = | var wordGroups = | ||
| from w in words | from w in words | ||
| group w by w[0] into g | group w by w[0] into g | ||
| select new { FirstLetter = g.Key, Words = g }; | select new { FirstLetter = g.Key, Words = g }; | ||
| - | + | </code> | |
| - | Anidación | + | === Anidación === |
| + | <code csharp> | ||
| var customerOrderGroups = | var customerOrderGroups = | ||
| from c in customers | from c in customers | ||
| Línea 107: | Línea 135: | ||
| } | } | ||
| }; | }; | ||
| + | </code> | ||
| - | Tipado anónimo | + | ==== Tipado anónimo ==== |
| + | <code csharp> | ||
| string[] words = { "aPPLE", "BlUeBeRrY", "cHeRry" }; | string[] words = { "aPPLE", "BlUeBeRrY", "cHeRry" }; | ||
| var upperLowerWords = | var upperLowerWords = | ||
| Línea 115: | Línea 145: | ||
| foreach (var ul in upperLowerWords) { | foreach (var ul in upperLowerWords) { | ||
| Console.WriteLine("Uppercase: {0}, Lowercase: {1}", ul.Upper, ul.Lower); | Console.WriteLine("Uppercase: {0}, Lowercase: {1}", ul.Upper, ul.Lower); | ||
| + | </code> | ||
| Otro... | Otro... | ||
| + | <code csharp> | ||
| var productInfos = | var productInfos = | ||
| from p in products | from p in products | ||
| Línea 122: | Línea 153: | ||
| foreach (var productInfo in productInfos) { | foreach (var productInfo in productInfos) { | ||
| Console.WriteLine("{0} is in the category {1} and costs {2} per unit.", productInfo.ProductName, productInfo.Category, productInfo.Price); | Console.WriteLine("{0} is in the category {1} and costs {2} per unit.", productInfo.ProductName, productInfo.Category, productInfo.Price); | ||
| + | </code> | ||
| Otro... | Otro... | ||
| + | <code csharp> | ||
| int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; | int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; | ||
| var numsInPlace = numbers.Select((num, index) => new {Num = num, InPlace = (num == index)}); | var numsInPlace = numbers.Select((num, index) => new {Num = num, InPlace = (num == index)}); | ||
| + | </code> | ||
| Otro... con asignación | Otro... con asignación | ||
| + | <code csharp> | ||
| var orders = | var orders = | ||
| from c in customers, | from c in customers, | ||
| Línea 134: | Línea 167: | ||
| where total >= 2000.0M | where total >= 2000.0M | ||
| select new {c.CustomerID, o.OrderID, total}; | select new {c.CustomerID, o.OrderID, total}; | ||
| - | + | </code> | |
| - | Relación de tablas | + | ==== Relación de tablas ==== |
| + | <code csharp> | ||
| var orders = | var orders = | ||
| from c in customers | from c in customers | ||
| Línea 142: | Línea 176: | ||
| where o.OrderDate >= cutoffDate | where o.OrderDate >= cutoffDate | ||
| select new {c.CustomerID, o.OrderID}; | select new {c.CustomerID, o.OrderID}; | ||
| + | </code> | ||
| - | Orderby | + | ==== Ordenación ==== |
| + | === Orderby === | ||
| + | <code csharp> | ||
| var sortedWords = | var sortedWords = | ||
| from w in words | from w in words | ||
| orderby w.Length | orderby w.Length | ||
| select w; | select w; | ||
| + | </code> | ||
| + | |||
| + | === Orderby Descending === | ||
| + | <code csharp> | ||
| + | var sortedWords = | ||
| + | from w in words | ||
| + | orderby w.Length descending | ||
| + | select w; | ||
| + | </code> | ||
| - | Cambiar el orden | + | === Cambiar el orden === |
| + | <code csharp> | ||
| var reversedIDigits = ( | var reversedIDigits = ( | ||
| from d in digits | from d in digits | ||
| Línea 155: | Línea 202: | ||
| select d) | select d) | ||
| .Reverse(); | .Reverse(); | ||
| + | </code> | ||
| - | Counts | + | ==== Contar elementos ==== |
| + | |||
| + | === Count === | ||
| + | <code csharp> | ||
| int[] factors = { 2, 2, 3, 5, 5 }; | int[] factors = { 2, 2, 3, 5, 5 }; | ||
| int uniqueFactors = factors.Distinct().Count(); | int uniqueFactors = factors.Distinct().Count(); | ||
| + | </code> | ||
| Devolvería 3 | Devolvería 3 | ||
| + | === Contar los impares === | ||
| - | Contar los impares: | + | <code csharp> |
| int oddNumbers = numbers.Count(n => n % 2 == 1); | int oddNumbers = numbers.Count(n => n % 2 == 1); | ||
| - | + | </code> | |
| - | Contar los carácteres de todas las palabras | + | === Contar los carácteres de todas las palabras === |
| + | <code csharp> | ||
| string[] words = { "cherry", "apple", "blueberry" }; | string[] words = { "cherry", "apple", "blueberry" }; | ||
| double totalChars = words.Sum(w => w.Length); | double totalChars = words.Sum(w => w.Length); | ||
| - | + | </code> | |
| - | Concatenar dos resultados | + | ==== Concatenación de resultados ==== |
| + | <code csharp> | ||
| var customerNames = | var customerNames = | ||
| from c in customers | from c in customers | ||
| Línea 176: | Línea 231: | ||
| select p.ProductName; | select p.ProductName; | ||
| var allNames = customerNames.Concat(productNames); | var allNames = customerNames.Concat(productNames); | ||
| - | + | </code> | |
| - | Escoger elementos | + | ==== Selección de elementos ==== |
| - | El primero | + | === El primero === |
| + | <code csharp> | ||
| Product product12 = ( | Product product12 = ( | ||
| from p in products | from p in products | ||
| Línea 184: | Línea 240: | ||
| select p ) | select p ) | ||
| .First(); | .First(); | ||
| - | + | </code> | |
| - | El cuarto... | + | === El cuarto === |
| + | <code csharp> | ||
| int fourthLowNum = ( | int fourthLowNum = ( | ||
| from n in numbers | from n in numbers | ||
| Línea 191: | Línea 248: | ||
| select n ) | select n ) | ||
| .ElementAt(3); | .ElementAt(3); | ||
| + | </code> | ||
| - | + | ===== Nuevas funciones ===== | |
| - | + | ==== Range ==== | |
| - | + | ||
| - | Nuevas funciones | + | |
| Generación de los números de 100 a 150: | Generación de los números de 100 a 150: | ||
| + | <code csharp> | ||
| from n in Sequence.Range(100, 50) | from n in Sequence.Range(100, 50) | ||
| + | </code> | ||
| + | ==== Repeat ==== | ||
| Repetición del número 7, 10 veces: | Repetición del número 7, 10 veces: | ||
| + | <code csharp> | ||
| var numbers = Sequence.Repeat(7, 10); | var numbers = Sequence.Repeat(7, 10); | ||
| + | </code> | ||
| - | Función Distinct | + | ==== Distinct ==== |
| Coge sólo uno, esquivando los elementos duplicados | Coge sólo uno, esquivando los elementos duplicados | ||
| + | <code csharp> | ||
| var categoryNames = ( | var categoryNames = ( | ||
| from p in products | from p in products | ||
| select p.Category) | select p.Category) | ||
| .Distinct(); | .Distinct(); | ||
| - | + | </code> | |
| - | Función Union | + | ==== Union ==== |
| Une dos listas del mismo tipo | Une dos listas del mismo tipo | ||
| + | <code csharp> | ||
| var uniqueNumbers = numbersA.Union(numbersB); | var uniqueNumbers = numbersA.Union(numbersB); | ||
| + | </code> | ||
| - | Función Intersect | + | ==== Intersect ==== |
| Coge los elementos que se repiten en las dos listas | Coge los elementos que se repiten en las dos listas | ||
| + | <code csharp> | ||
| var commonNumbers = numbersA.Intersect(numbersB); | var commonNumbers = numbersA.Intersect(numbersB); | ||
| - | + | </code> | |
| - | Función Except | + | ==== Except ==== |
| Coge los elementos de la primera lista que no esten en la segunda | Coge los elementos de la primera lista que no esten en la segunda | ||
| + | <code csharp> | ||
| IEnumerable<int> aOnlyNumbers = numbersA.Except(numbersB); | IEnumerable<int> aOnlyNumbers = numbersA.Except(numbersB); | ||
| - | + | </code> | |
| - | Función Take | + | ==== Take ==== |
| Coge los primeros valores | Coge los primeros valores | ||
| + | <code csharp> | ||
| var first3Numbers = numbers.Take(3); | var first3Numbers = numbers.Take(3); | ||
| + | </code> | ||
| + | <code csharp> | ||
| var first3WAOrders = ( | var first3WAOrders = ( | ||
| from c in customers | from c in customers | ||
| Línea 232: | Línea 299: | ||
| select new {c.CustomerID, o.OrderID, o.OrderDate} ) | select new {c.CustomerID, o.OrderID, o.OrderDate} ) | ||
| .Take(3); | .Take(3); | ||
| + | </code> | ||
| - | Función Skip | + | |
| + | ==== Skip ==== | ||
| Coge los últimos números saltandose los indicados | Coge los últimos números saltandose los indicados | ||
| + | <code csharp> | ||
| var allButFirst4Numbers = numbers.Skip(4); | var allButFirst4Numbers = numbers.Skip(4); | ||
| - | + | </code> | |
| - | Combinación de skip y take | + | === Combinación de skip y take === |
| + | <code csharp> | ||
| query.Skip(30).Take(10) | query.Skip(30).Take(10) | ||
| + | </code> | ||
| + | |||
| + | |||
| + | |||
| + | ===== Otros ===== | ||
| + | |||
| + | |||
| + | ==== let ==== | ||
| + | La clausula ''let'' permite crear una variable dentro del ámbito de la query y utilizarla en la condición. | ||
| + | |||
| + | <code csharp> | ||
| + | var lArrivals = from a in db.PIU_ARRIVALS | ||
| + | let t = (DateTime.Now - a.updatedLocalTime) | ||
| + | where (t.Seconds > seconds) | ||
| + | select a; | ||
| + | </code> | ||
| + | ... O ... | ||
| + | <code csharp> | ||
| + | from car in root.Elements("car") | ||
| + | let profiles = | ||
| + | from profile in car.Elements("profile") | ||
| + | select new { | ||
| + | Name = profile.Attribute("name").Value, | ||
| + | Value = profile.Attribute("value").Value | ||
| + | } | ||
| + | let supports = | ||
| + | from support in car.Elements("support") | ||
| + | select new { | ||
| + | Name = support.Attribute("name").Value, | ||
| + | Value = support.Attribute("value").Value | ||
| + | } | ||
| + | select new Car { | ||
| + | Name = car.Attribute("name").Value, | ||
| + | Vendor = profiles.Single(prof => prof.Name == "Vendor").Value, | ||
| + | Model = profiles.Single(prof => prof.Name == "Model").Value, | ||
| + | Doors = int.Parse(profiles.Single(prof => prof.Name == "Doors").Value), | ||
| + | RacingSupport = supports.Single(sup => sup.Name == "Racing").Value == "yes" | ||
| + | }; | ||
| + | </code> | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | ===== Ejemplos ===== | ||
| + | === Ejemplo 1 === | ||
| + | SQL: | ||
| + | <code sql> | ||
| + | SELECT SAE_LINEASPIENPANELINFO.INUMEROORDEN, SAE_LINEASPIENPANELINFO.SNOMBRELINEA, SAE_LINEASPIENPANELINFO.SNOMBREDESTINO, | ||
| + | SAE_LINEASPIENPANELINFO.IIDLINEA, SAE_LINEASPIENPANELINFO.IIDTRAYECTO, SAE_LINEASPIENPANELINFO.IIDPARADA | ||
| + | FROM SAE_LINEASPIENPANELINFO, SAE_CONFBIENPROGRAMADAS | ||
| + | WHERE SAE_LINEASPIENPANELINFO.IIDPARADA = {0} AND SAE_LINEASPIENPANELINFO.IIDPANELINFO = {1} | ||
| + | AND SAE_CONFBIENPROGRAMADAS.IIDCONFLINEASACTUAL = SAE_LINEASPIENPANELINFO.IIDCONFIGURACIONLINEASPI | ||
| + | AND SAE_CONFBIENPROGRAMADAS.IIDPANELINFO = {1} | ||
| + | ORDER BY SAE_LINEASPIENPANELINFO.INUMEROORDEN | ||
| + | </code> | ||
| + | LINQ: | ||
| + | <code csharp> | ||
| + | var dades = from linies in dbdc.SAE_LINEASPIENPANELINFO | ||
| + | from conf in dbdc.SAE_CONFBIENPROGRAMADAS | ||
| + | orderby linies.INUMEROORDEN | ||
| + | where ((linies.IIDPARADA == p.IIDPARADA) && | ||
| + | (linies.IIDPANELINFO == codi) && | ||
| + | (conf.IIDCONFLINEASACTUAL == linies.IIDCONFIGURACIONLINEASPI) && | ||
| + | (conf.IIDPANELINFO == codi)) | ||
| + | select new | ||
| + | { | ||
| + | INUMEROORDEN = linies.INUMEROORDEN, | ||
| + | SNOMBRELINEA = linies.SNOMBRELINEA, | ||
| + | SNOMBREDESTINO = linies.SNOMBREDESTINO, | ||
| + | IIDLINEA = linies.IIDLINEA, | ||
| + | IIDTRAYECTO = linies.IIDTRAYECTO, | ||
| + | IIDPARADA = linies.IIDPARADA | ||
| + | }; | ||
| + | </code> | ||
| + | === Ejemplo 2 (combinación) === | ||
| + | Esto... | ||
| + | <code> | ||
| + | var id_paradas = (from pt in db.SAE_PARADASTRAYECTO | ||
| + | where (pt.IIDLINEA == idLinia) | ||
| + | select pt.IIDPARADA.GetValueOrDefault(-1)).Distinct(); | ||
| + | |||
| + | return (from p in db.SAE_PARADAS | ||
| + | from id in id_paradas | ||
| + | where (p.IIDPARADA == id) | ||
| + | select p).ToList(); | ||
| + | </code> | ||
| + | Es igual a... | ||
| + | <code> | ||
| + | return (from p in db.SAE_PARADAS | ||
| + | from id in ((from pt in db.SAE_PARADASTRAYECTO | ||
| + | where (pt.IIDLINEA == idLinia) | ||
| + | select pt.IIDPARADA.GetValueOrDefault(-1)).Distinct()) | ||
| + | where (p.IIDPARADA == id) | ||
| + | select p).ToList(); | ||
| + | </code> | ||
| + | === Ejemplo 3 (NOT IN) === | ||
| + | <code> | ||
| + | var query = | ||
| + | from c in dc.Customers | ||
| + | where !(from o in dc.Orders | ||
| + | select o.CustomerID) | ||
| + | .Contains(c.CustomerID) | ||
| + | select c; | ||
| + | foreach (var c in query) Console.WriteLine( c ); | ||
| + | </code> | ||
| + | === Ejemplo 4 (FindAll y ForEach) === | ||
| + | <code> | ||
| + | static void DisplayInstalledApplications2() | ||
| + | { | ||
| + | string registryKey = | ||
| + | @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"; | ||
| + | |||
| + | using (Microsoft.Win32.RegistryKey key = | ||
| + | Registry.LocalMachine.OpenSubKey(registryKey)) | ||
| + | { | ||
| + | (from a in key.GetSubKeyNames() | ||
| + | let r = key.OpenSubKey(a) | ||
| + | select new | ||
| + | { | ||
| + | Application = r.GetValue("DisplayName") | ||
| + | }).ToList() | ||
| + | .FindAll(c => c.Application != null) | ||
| + | .ForEach(c => Console.WriteLine(c.Application)); | ||
| + | } | ||
| + | } | ||
| + | </code> | ||
| + | === Cálculo del tamaño de un directorio === | ||
| + | <code csharp> | ||
| + | static long DirectorySize(DirectoryInfo dInfo, bool includeSubDir) { | ||
| + | // Enumerate all the files | ||
| + | long totalSize = dInfo.EnumerateFiles() | ||
| + | .Sum(file => file.Length); | ||
| + | // If Subdirectories are to be included | ||
| + | if (includeSubDir) | ||
| + | { | ||
| + | // Enumerate all sub-directories | ||
| + | totalSize += dInfo.EnumerateDirectories() | ||
| + | .Sum(dir => DirectorySize(dir, true)); | ||
| + | } | ||
| + | return totalSize; | ||
| + | } | ||
| + | </code> | ||
| + | ===== Notas ===== | ||
| + | * En las querys LINQ podemos ver el código SQL generado; si se debuga se puede ver el comando sql en la variable a la que se le ha asignado dicha query. | ||
| + | * El resultado de una sentencia LINQ puede ser asignada a un ''DataSource'' de un ''GridView''. Luego tendremos que llamar al método ''DataBind'' para que se muestren. | ||