LINQ – Language Integrated Query Dalton Cézane Wireless Laboratório de Instrumentação Eletrônica e Controle
O que é LINQ? Existe o problema de se manipular dados e objetos de duas maneiras diferentes: declarativa, para dados, e imperativa, para objetos; LINQ é um modelo de programação unificado para “qualquer tipo de dado”; Introduz mais sintaxe declarativa: ajuda o sistema a encontrar a melhor estratégia de execução.
Hello LINQ! using System; using System.Linq; string[ ] saudacoes = { "Oi LIEC", "Oi LINQ", "Oi turma" }; var itens = from s in saudacoes where s.EndsWith("LINQ") select s; foreach (var item in itens) Console.WriteLine(item);
Consultas em XML using System; using System.Linq; using System.Xml.Linq; XElement livros = XElement.Parse( @&quot;< livros> < livro> <titulo>Pro LINQ: Language Integrated Query in C# 2008</titulo> <autor>Joe Rattz</autor> </ livro> < livro> <titulo>Pro WF: Windows Workflow in .NET 3.0</titulo> <autor>Bruce Bukovics</autor> </ livro> < livro> <titulo>Pro C# 2005 and the .NET 2.0 Platform, Third Edition</titulo> <autor>Andrew Troelsen</autor> </ livro> </ livros>&quot;);
Consultas em XML var titulos = from livro in livros.Elements(“livro&quot;) where (string) livro.Element(&quot;autor&quot;) == &quot;Joe Rattz&quot; select livro.Element(&quot;titulo&quot;); foreach(var titulo in titulos) Console.WriteLine(titulo.Value);
Consultas em SQL Server using System; using System.Linq; using System.Data.Linq; using nwind; Northwind db = new Northwind(@&quot;Data Source=.\SQLEXPRESS;Initial Catalog=Northwind&quot;); var clientes = from c in db.Clientes where c.Cidade == &quot;Rio de Janeiro&quot; select c; foreach (var cliente in clientes) Console.WriteLine(&quot;{0}&quot;, cliente. NomeCompanhia);
Consultas: tipos retornados IEnumerable<T>: tipo de retorno das seqüências obtidas pelas consultas realizadas em objetos (conjuntos de objetos); IQueryable<T>: tipo de retorno das seqüências obtidas pelas consultas realizadas com SQL (bases de dados); T é o tipo de dados dos objetos armazenados na seqüência de retorno de uma consulta;
Componentes LINQ para objetos (arrays e coleções de dados na memória -  System.Linq.Enumerable); LINQ para XML (lidar com arquivos XML -  using  System.Xml.Linq); LINQ para DataSets (consultas relacionadas com DataSets); LINQ para SQL (API  IQueryable<T> que permite trabalhar com bancos de dados SQL Server - using System.Data.Linq);
Componentes LINQ para entidades: uma alternativa para se trabalhar desacoplando o modelo de objetos do banco de dados físico, através de um mapeamento lógico entre os dois. Isto pode prover maior flexibilidade e poder ao sistema.
Arquitetura . Net Language Integrated Queries LINQ para Objetos LINQ para SQL LINQ para XML Objetos Bases de dados <xml> XML C# 3.0 VB9 Outras…
LINQ não é apenas para consultas Converter um array de strings em um array de inteiros: string[] numeros = { &quot;0042&quot;, &quot;010&quot;, &quot;9&quot;, &quot;27&quot; }; int[] nums = numeros.Select(s => Int32.Parse(s)).ToArray(); Realizar o mesmo processo ordenando o array de inteiros: string[] numeros = { &quot;0042&quot;, &quot;010&quot;, &quot;9&quot;, &quot;27&quot; }; int[] nums = numeros.Select(s => Int32.Parse(s)).OrderBy(s => s).ToArray();
var Usar a palavra-chave “var”, quando não tiver certeza de um tipo de retorno: // Este código não compila. Northwind db = new Northwind(@&quot;Data Source=.\SQLEXPRESS;Initial Catalog=Northwind&quot;); IEnumerable< ? > pedidos = db.Clientes .Where(c => c.País == “Brasil&quot; && c.Regiao == “Ne&quot;) .SelectMany(c => c.Pedidos);
var //Agora compila. Northwind db = new Northwind(@&quot;DataSource=.\SQLEXPRESS;Initial Catalog=Northwind&quot;); var pedidos = db.Clientes .Where(c => c.País == “Brasil&quot; && c.Regiao == “Ne&quot;) .SelectMany(c => c.Pedidos); Console.WriteLine(pedidos.GetType()); Resultado:  System.Data.Linq.DataQuery`1[nwind.Pedidos]
Lazy evaluation var numeros = new List<int>( ); numeros.Add (1); // Constrói consulta IEnumerable<int> consulta = numeros.Select (n => n * 10); numeros.Add (2); // Adicionando um elemento foreach (int n in consulta) Console.Write (n + &quot;|&quot;); // 10|20|
Lazy evaluation var numeros = new List<int>( ) { 1, 2 }; IEnumerable<int> consulta = numeros.Select (n => n * 10); foreach (int n in consulta) Console.Write (n + &quot;|&quot;); // 10|20| numbers.Clear( ); foreach (int n in consulta) Console.Write (n + &quot;|&quot;); // nada
Lazy evaluation int fator = 10;  var consulta2 = numeros.Select (n => n * fator); fator = 20; // Alterando o fator foreach (int n in consulta2) Console.Write (n + &quot;|&quot;); // 20|40|
Cast  ou  OfType Como usar LINQ com coleções “legadas” em código base existente? A diferença entre Cast e OfType é: o primeiro testa todos os tipos dos objetos e caso haja algum no qual não possa ser realizado o cast uma exceção é lançada, já no segundo são recuperados apenas os elementos nos quais se pode realizar “cast”.
Operador  Cast // I'll build a legacy collection. ArrayList arrayList = new ArrayList(); // Sure wish I could use collection initialization here, but that // doesn't work with legacy collections. arrayList.Add(&quot;Adams&quot;); arrayList.Add(&quot;Arthur&quot;); arrayList.Add(&quot;Buchanan&quot;); IEnumerable<string> nomes = arrayList. Cast <string>().Where(n => n.Length < 7); foreach(string nome in nomes) Console.WriteLine(nome);
Operador  OfType // I'll build a legacy collection. ArrayList arrayList = new ArrayList(); // Sure wish I could use collection initialization here, but that // doesn't work with legacy collections. arrayList.Add(&quot;Adams&quot;); arrayList.Add(&quot;Arthur&quot;); arrayList.Add(&quot;Buchanan&quot;); IEnumerable<string> nomes = arrayList. OfType <string>().Where(n => n.Length < 7); foreach(string nome in nomes) Console.WriteLine(nome);
Dica Cuidado ao inicializar uma consulta em determinada variável, pois erros só serão percebidos quando a mesma for executada.
Exemplo string[] strings = { “um&quot;, “dois&quot;,  null , “três&quot; }; Console.WriteLine(“Antes do Where() ser chamado.&quot;); IEnumerable<string> ieStrings = strings.Where(s =>  s.Length == 3 ); Console.WriteLine(“Depois do Where() ser chamado.&quot;); foreach(string s in ieStrings) { Console.WriteLine(&quot;Processando &quot; + s); }
Exemplo    Resultado: Antes do Where() ser chamado. Depois do Where() ser chamado. Processando um Processando dois Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object. …
Expressões  Lambda var  filteredNames = names.Where (n => n.Length >= 4); IEnumerable<string> filteredNames = from n in names where n.Length >= 4 select n;
Expressões  Lambda string[] nomes = { &quot;Tom&quot;,&quot;Dick&quot;,&quot;Harry&quot;,&quot;Mary&quot;,&quot;Jay&quot; }; IEnumerable<string> consulta = nomes .Where (n => n.Contains (&quot;a&quot;)) .OrderBy (n => n.Length) .Select (n => n.ToUpper( )); foreach (string nome in consulta) Console.Write (nome + &quot;|&quot;); // RESULTADO: JAY|MARY|HARRY| //Operadores padrão: where, orderby, select...
Expressões  Lambda Outra maneira de se fazer: var filtrados = nomes.Where (n => n.Contains (&quot;a&quot;)); var ordenados = filtrados.OrderBy (n => n.Length); var consultaFinal = ordenados.Select (n => n.ToUpper( )); foreach (string nome in filtrados) Console.Write (nome + &quot;|&quot;); // Harry|Mary|Jay| Console.WriteLine( ); foreach (string nome in ordenados) Console.Write (nome + &quot;|&quot;); // Jay|Mary|Harry| Console.WriteLine( ); foreach (string nome in consultaFinal) Console.Write (nome + &quot;|&quot;); // JAY|MARY|HARRY|
Sub-consultas string[] nomes = { &quot;David Gilmour&quot;,&quot;Roger Waters&quot;, &quot;Rick Wright&quot;}; IEnumerable<string> consulta = nomes.OrderBy (m => m.Split() .Last() ); //Last é uma sub-consulta
Sub-consultas string[] nomes = { &quot;Tom&quot;,&quot;Dick&quot;,&quot;Harry&quot;,&quot;Mary&quot;,&quot;Jay&quot; }; IEnumerable<string> consulta1 = nomes .Where (n => n.Length == nomes.OrderBy (n2 => n2.Length) .Select (n2 => n2.Length).First( ));  // Resultado: Tom, Jay IEnumerable<string> consulta2 = from n in nomes where n.Length == (from n2 in nomes orderby n2.Length select n2.Length).First( )) select n; // “comprehension query”
Sub-consultas IEnumerable<string> consulta3 = from n in nomes where n.Length == nomes.OrderBy (n2 => n2.Length).First( ).Length select n; IEnumerable<string> consulta4 = from n in nomes where n.Length == nomes.Min (n2 => n2.Length) select n; // com uso de Min
Sub-consultas int menor = nomes.Min (n => n.Length); IEnumerable<string> consulta6 =  from n in nomes where n.Length == menor select n;
Referências RATTZ Jr, Joseph C. Pro LINQ – Language Integrated Query in C# 2008. Apress. 2007. EL-DIN, Mohammed Hossam. C# 3.0 & LINQ Project presentation. Linqpocket.

LINQ - Language Integrated Query

  • 1.
    LINQ – LanguageIntegrated Query Dalton Cézane Wireless Laboratório de Instrumentação Eletrônica e Controle
  • 2.
    O que éLINQ? Existe o problema de se manipular dados e objetos de duas maneiras diferentes: declarativa, para dados, e imperativa, para objetos; LINQ é um modelo de programação unificado para “qualquer tipo de dado”; Introduz mais sintaxe declarativa: ajuda o sistema a encontrar a melhor estratégia de execução.
  • 3.
    Hello LINQ! usingSystem; using System.Linq; string[ ] saudacoes = { &quot;Oi LIEC&quot;, &quot;Oi LINQ&quot;, &quot;Oi turma&quot; }; var itens = from s in saudacoes where s.EndsWith(&quot;LINQ&quot;) select s; foreach (var item in itens) Console.WriteLine(item);
  • 4.
    Consultas em XMLusing System; using System.Linq; using System.Xml.Linq; XElement livros = XElement.Parse( @&quot;< livros> < livro> <titulo>Pro LINQ: Language Integrated Query in C# 2008</titulo> <autor>Joe Rattz</autor> </ livro> < livro> <titulo>Pro WF: Windows Workflow in .NET 3.0</titulo> <autor>Bruce Bukovics</autor> </ livro> < livro> <titulo>Pro C# 2005 and the .NET 2.0 Platform, Third Edition</titulo> <autor>Andrew Troelsen</autor> </ livro> </ livros>&quot;);
  • 5.
    Consultas em XMLvar titulos = from livro in livros.Elements(“livro&quot;) where (string) livro.Element(&quot;autor&quot;) == &quot;Joe Rattz&quot; select livro.Element(&quot;titulo&quot;); foreach(var titulo in titulos) Console.WriteLine(titulo.Value);
  • 6.
    Consultas em SQLServer using System; using System.Linq; using System.Data.Linq; using nwind; Northwind db = new Northwind(@&quot;Data Source=.\SQLEXPRESS;Initial Catalog=Northwind&quot;); var clientes = from c in db.Clientes where c.Cidade == &quot;Rio de Janeiro&quot; select c; foreach (var cliente in clientes) Console.WriteLine(&quot;{0}&quot;, cliente. NomeCompanhia);
  • 7.
    Consultas: tipos retornadosIEnumerable<T>: tipo de retorno das seqüências obtidas pelas consultas realizadas em objetos (conjuntos de objetos); IQueryable<T>: tipo de retorno das seqüências obtidas pelas consultas realizadas com SQL (bases de dados); T é o tipo de dados dos objetos armazenados na seqüência de retorno de uma consulta;
  • 8.
    Componentes LINQ paraobjetos (arrays e coleções de dados na memória - System.Linq.Enumerable); LINQ para XML (lidar com arquivos XML - using System.Xml.Linq); LINQ para DataSets (consultas relacionadas com DataSets); LINQ para SQL (API IQueryable<T> que permite trabalhar com bancos de dados SQL Server - using System.Data.Linq);
  • 9.
    Componentes LINQ paraentidades: uma alternativa para se trabalhar desacoplando o modelo de objetos do banco de dados físico, através de um mapeamento lógico entre os dois. Isto pode prover maior flexibilidade e poder ao sistema.
  • 10.
    Arquitetura . NetLanguage Integrated Queries LINQ para Objetos LINQ para SQL LINQ para XML Objetos Bases de dados <xml> XML C# 3.0 VB9 Outras…
  • 11.
    LINQ não éapenas para consultas Converter um array de strings em um array de inteiros: string[] numeros = { &quot;0042&quot;, &quot;010&quot;, &quot;9&quot;, &quot;27&quot; }; int[] nums = numeros.Select(s => Int32.Parse(s)).ToArray(); Realizar o mesmo processo ordenando o array de inteiros: string[] numeros = { &quot;0042&quot;, &quot;010&quot;, &quot;9&quot;, &quot;27&quot; }; int[] nums = numeros.Select(s => Int32.Parse(s)).OrderBy(s => s).ToArray();
  • 12.
    var Usar apalavra-chave “var”, quando não tiver certeza de um tipo de retorno: // Este código não compila. Northwind db = new Northwind(@&quot;Data Source=.\SQLEXPRESS;Initial Catalog=Northwind&quot;); IEnumerable< ? > pedidos = db.Clientes .Where(c => c.País == “Brasil&quot; && c.Regiao == “Ne&quot;) .SelectMany(c => c.Pedidos);
  • 13.
    var //Agora compila.Northwind db = new Northwind(@&quot;DataSource=.\SQLEXPRESS;Initial Catalog=Northwind&quot;); var pedidos = db.Clientes .Where(c => c.País == “Brasil&quot; && c.Regiao == “Ne&quot;) .SelectMany(c => c.Pedidos); Console.WriteLine(pedidos.GetType()); Resultado: System.Data.Linq.DataQuery`1[nwind.Pedidos]
  • 14.
    Lazy evaluation varnumeros = new List<int>( ); numeros.Add (1); // Constrói consulta IEnumerable<int> consulta = numeros.Select (n => n * 10); numeros.Add (2); // Adicionando um elemento foreach (int n in consulta) Console.Write (n + &quot;|&quot;); // 10|20|
  • 15.
    Lazy evaluation varnumeros = new List<int>( ) { 1, 2 }; IEnumerable<int> consulta = numeros.Select (n => n * 10); foreach (int n in consulta) Console.Write (n + &quot;|&quot;); // 10|20| numbers.Clear( ); foreach (int n in consulta) Console.Write (n + &quot;|&quot;); // nada
  • 16.
    Lazy evaluation intfator = 10; var consulta2 = numeros.Select (n => n * fator); fator = 20; // Alterando o fator foreach (int n in consulta2) Console.Write (n + &quot;|&quot;); // 20|40|
  • 17.
    Cast ou OfType Como usar LINQ com coleções “legadas” em código base existente? A diferença entre Cast e OfType é: o primeiro testa todos os tipos dos objetos e caso haja algum no qual não possa ser realizado o cast uma exceção é lançada, já no segundo são recuperados apenas os elementos nos quais se pode realizar “cast”.
  • 18.
    Operador Cast// I'll build a legacy collection. ArrayList arrayList = new ArrayList(); // Sure wish I could use collection initialization here, but that // doesn't work with legacy collections. arrayList.Add(&quot;Adams&quot;); arrayList.Add(&quot;Arthur&quot;); arrayList.Add(&quot;Buchanan&quot;); IEnumerable<string> nomes = arrayList. Cast <string>().Where(n => n.Length < 7); foreach(string nome in nomes) Console.WriteLine(nome);
  • 19.
    Operador OfType// I'll build a legacy collection. ArrayList arrayList = new ArrayList(); // Sure wish I could use collection initialization here, but that // doesn't work with legacy collections. arrayList.Add(&quot;Adams&quot;); arrayList.Add(&quot;Arthur&quot;); arrayList.Add(&quot;Buchanan&quot;); IEnumerable<string> nomes = arrayList. OfType <string>().Where(n => n.Length < 7); foreach(string nome in nomes) Console.WriteLine(nome);
  • 20.
    Dica Cuidado aoinicializar uma consulta em determinada variável, pois erros só serão percebidos quando a mesma for executada.
  • 21.
    Exemplo string[] strings= { “um&quot;, “dois&quot;, null , “três&quot; }; Console.WriteLine(“Antes do Where() ser chamado.&quot;); IEnumerable<string> ieStrings = strings.Where(s => s.Length == 3 ); Console.WriteLine(“Depois do Where() ser chamado.&quot;); foreach(string s in ieStrings) { Console.WriteLine(&quot;Processando &quot; + s); }
  • 22.
    Exemplo  Resultado: Antes do Where() ser chamado. Depois do Where() ser chamado. Processando um Processando dois Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object. …
  • 23.
    Expressões Lambdavar filteredNames = names.Where (n => n.Length >= 4); IEnumerable<string> filteredNames = from n in names where n.Length >= 4 select n;
  • 24.
    Expressões Lambdastring[] nomes = { &quot;Tom&quot;,&quot;Dick&quot;,&quot;Harry&quot;,&quot;Mary&quot;,&quot;Jay&quot; }; IEnumerable<string> consulta = nomes .Where (n => n.Contains (&quot;a&quot;)) .OrderBy (n => n.Length) .Select (n => n.ToUpper( )); foreach (string nome in consulta) Console.Write (nome + &quot;|&quot;); // RESULTADO: JAY|MARY|HARRY| //Operadores padrão: where, orderby, select...
  • 25.
    Expressões LambdaOutra maneira de se fazer: var filtrados = nomes.Where (n => n.Contains (&quot;a&quot;)); var ordenados = filtrados.OrderBy (n => n.Length); var consultaFinal = ordenados.Select (n => n.ToUpper( )); foreach (string nome in filtrados) Console.Write (nome + &quot;|&quot;); // Harry|Mary|Jay| Console.WriteLine( ); foreach (string nome in ordenados) Console.Write (nome + &quot;|&quot;); // Jay|Mary|Harry| Console.WriteLine( ); foreach (string nome in consultaFinal) Console.Write (nome + &quot;|&quot;); // JAY|MARY|HARRY|
  • 26.
    Sub-consultas string[] nomes= { &quot;David Gilmour&quot;,&quot;Roger Waters&quot;, &quot;Rick Wright&quot;}; IEnumerable<string> consulta = nomes.OrderBy (m => m.Split() .Last() ); //Last é uma sub-consulta
  • 27.
    Sub-consultas string[] nomes= { &quot;Tom&quot;,&quot;Dick&quot;,&quot;Harry&quot;,&quot;Mary&quot;,&quot;Jay&quot; }; IEnumerable<string> consulta1 = nomes .Where (n => n.Length == nomes.OrderBy (n2 => n2.Length) .Select (n2 => n2.Length).First( )); // Resultado: Tom, Jay IEnumerable<string> consulta2 = from n in nomes where n.Length == (from n2 in nomes orderby n2.Length select n2.Length).First( )) select n; // “comprehension query”
  • 28.
    Sub-consultas IEnumerable<string> consulta3= from n in nomes where n.Length == nomes.OrderBy (n2 => n2.Length).First( ).Length select n; IEnumerable<string> consulta4 = from n in nomes where n.Length == nomes.Min (n2 => n2.Length) select n; // com uso de Min
  • 29.
    Sub-consultas int menor= nomes.Min (n => n.Length); IEnumerable<string> consulta6 = from n in nomes where n.Length == menor select n;
  • 30.
    Referências RATTZ Jr,Joseph C. Pro LINQ – Language Integrated Query in C# 2008. Apress. 2007. EL-DIN, Mohammed Hossam. C# 3.0 & LINQ Project presentation. Linqpocket.