Date post: | 15-Jul-2015 |
Category: |
Software |
Upload: | thiago-vidal |
View: | 480 times |
Download: | 0 times |
Introdução ao LINQ
Inferência de Tipos
Tipos Anônimos
Expressões Lambda
Métodos de Extensão
LINQ to SQL: Introdução
LINQ to SQL: Integração com o Visual Studio
LINQ Providers
29/03/2015LINQ via C# - .Net Coders 2
O que é LINQ?
Language Integrated Query
Biblioteca de consulta a dados
Incorporado ao .Net Framework 3.5, lançado com a versão 3.0 do C#
Por que LINQ é necessário?
Permite ao desenvolvedor criar expressões de consulta em qualquer fonte de dados
Sintaxe prática e enxuta
Escrever menos código facilita a manipulação de dados
29/03/2015LINQ via C# - .Net Coders 3
Uma query (ou consulta) é uma expressão que extrai dados de uma fonte de dados
Geralmente, as queries são escritas com uma linguagem específica para cada fonte de dados. Ex: SQL para BDs relacionais e XQuery para XML.
Não é vantajoso para o desenvolvedor ter de aprender uma linguagem nova para cada fonte de dados
É aí que entra o LINQ que fornece um modelo unificado (e simplificado) para manipular dados com o .Net
29/03/2015LINQ via C# - .Net Coders 4
Escrevendo a primeira query – LINQ to Objects
Uma query LINQ consiste de 3 operações distintas:
1. Obter o data source (fonte de dados)
2. Criar a query
3. Executar a query
29/03/2015LINQ via C# - .Net Coders 5
A fonte de dados neste exemplo é um array de inteiros
Dois lados da query: o lado esquerdo (atribuição) e o lado direito (filtro)
Note que para fazer um filtro não basta apenas criar uma variável.
Construindo o filtro: Começa com a palavra-chave ‘from’
Crie uma variável (num) que referencia os elementos da fonte de dados
Especifique a fonte de dados (in arrNums)
O ‘where’ aplica alguma condição específica, embora não seja necessário
O ‘select’ seleciona os elementos filtrados
Um laço (foreach) irá iterar sobre o lado direito da query para imprimir seu resultado
29/03/2015LINQ via C# - .Net Coders 7
Para ser possível a iteração sobre os elementos de uma fonte de dados, é necessário que essa classe implemente a interface IEnumerable<T>. Os tipos primitivos do .Net Framework já implementam por padrão essa interface.
Então, a query é executada dentro de um foreach.
29/03/2015LINQ via C# - .Net Coders 8
IEnumerable<T> e Generics
As consultas LINQ são baseadas em Generics
Dois conceitos-chave:
Quando você cria uma instância de uma classe genérica, você substitui o ‘T’ pelo tipo instanciado. Por exemplo, ao criar uma List de string, o ‘T’ é substituído por ‘string’.
A interface genérica IEnumerable<T> permite a iteração sobre elementos de classes que a implementam
29/03/2015LINQ via C# - .Net Coders 9
Neste exemplo, é criada uma lista de Pessoas e a query seleciona todas as pessoas;
O tipo retornado pela consulta é um IEnumerable<Pessoa>
29/03/2015LINQ via C# - .Net Coders 10
É possível “omitir” a notação genérica pelo uso da palavra-chave var;
Ao referenciar uma variável com ‘var’ o compilador infere, ou seja, resolve emtempo de compilação o tipo daquela variável.
No exemplo a seguir será feito um filtro de pessoas do sexo feminino:
29/03/2015LINQ via C# - .Net Coders 11
Regras de utilização:
Erros de compilação:
Declarar uma variável com var e não atribuir nenhum valor
Atribuir null a uma variável var
Declarar um atributo como var (use-o somente como variável local)
Recomenda-se usar var quando:
Queries LINQ
Tipos por referência
29/03/2015LINQ via C# - .Net Coders 13
É um recurso para encapsular propriedades a um objeto sem ter de criar um novo tipo (uma nova classe) para isso;
O nome do tipo é gerado pelo compilador e o tipo de suas propriedades é inferido por ele;
O tipo não é acessível no código-fonte;
As propriedades de um tipo anônimo são read-only
Não podem ser usados como atributos;
Um tipo anônimo é definido sempre com a palavra-chave var;
29/03/2015LINQ via C# - .Net Coders 15
Como criar um tipo anônimo:
Perceba que as propriedades de um tipo anônimo são imutáveis. Não é possível a escrita (set).
29/03/2015LINQ via C# - .Net Coders 16
Exemplo de utilização: projeções em expressões LINQ
O que é uma projeção?
A cláusula select pode ser utilizada para retornar um subconjunto específico das propriedades de cada objeto na fonte de dados muitas vezes diferente dos dados originais
Útil quando você quer guardar algumas informações de cada objeto em uma sequência
Select new {...};
29/03/2015LINQ via C# - .Net Coders 17
Exemplo: selecionar alunos com as maiores notas da turma (maior ou igual a 7)
29/03/2015LINQ via C# - .Net Coders 18
Exemplo: selecionar alunos que possuem uma dependência em Álgebra Linear
29/03/2015LINQ via C# - .Net Coders 19
Uma expressão lambda é uma função anônima com a qual é possível criar delegates ou árvores de expressão
Você pode usar uma expressão lambda como uma função local e passar argumentos ou retornar valores de funções
Muito útil para escrever consultas LINQ
Primeiro exemplo: lambda com delegate
29/03/2015LINQ via C# - .Net Coders 20
Os delegates são definidos em uma outra classe. Ou, se estiver usando no Main, defina-o fora dele:
Outro exemplo
29/03/2015LINQ via C# - .Net Coders 21
Delegates funcionam como referências a métodos e são base para criar eventos no .Net. São como protótipos de funções (C/C++) inclusive.
Nos exemplos anteriores, foi definido utilizando uma expressão lambda o delegate para multiplicar um número por ele mesmo. E depois, em uma variável armazena-se o resultado da chamada do delegate.
Para criar uma expressão lambda você lista parâmetros de entrada (caso tenha) no lado esquerdo do operador =>, e a expressão em si (o filtro) fica do lado direito.
Ex.: A expressão x => x * x especifica o parâmetro x que armazena o retorno de x * x.
Ex2: A expressão (x,y) => x – y especifica dois parâmetros x e y para ser realizada umasubtração. Os argumentos nesta chamada, segundo o exemplo anterior, são 10 e 5 (emsubtrairDelegate(10,5))
29/03/2015LINQ via C# - .Net Coders 22
Utilizando o mesmo array do primeiro exemplo, faremos uma expressão lambda para retornar os números ímpares deste array:
Perceba que a expressão fica bem mais enxuta em comparação às demais. O filtro é feito por meio do método de extensão Where.
29/03/2015LINQ via C# - .Net Coders 23
Na versão 3.0 do C# foi introduzida uma nova feature chamada métodos de extensão, que permite ao desenvolvedor acrescentar novos métodos em classes existentes sem ter de utilizar os recursos de herança, ou até implementar alguma modificação no arquivo original.
Como funciona? Os métodos de extensão são definidos como estáticos (em classes também estáticas), mas são chamados como os métodos de instância.
Ex.: criamos uma classe chamada MyExtensions e definimos nela um método ToURL, que transforma uma string qualquer em uma URL:
29/03/2015LINQ via C# - .Net Coders 24
O que acontece, na verdade, é que estamos adicionando um método à classe String do .Net. Para isso funcionar, basta escrever ‘this’ no parâmetro antes do nome da classe, como mostra o slide anterior.
Uma observação é que o IntelliSense identifica um método de extensão pela seta azul ao lado do nome do método. Podemos ver que os métodos do LINQ que utilizamos no dia a dia são de extensão, definidos na classe Enumerable.
29/03/2015LINQ via C# - .Net Coders 25
Apresentando outros métodos de extensão
Average: retorna a média dos valores em uma coleção
ElementAt: retorna o elemento em determinada posição
29/03/2015LINQ via C# - .Net Coders 26
ElementAtOrDefault: retorna o elemento em determinada posição, ou null, caso a posição seja inválida.
OrderBy, GroupBy:
Crie a classe Funcionario:
29/03/2015LINQ via C# - .Net Coders 27
Instancie 10 objetos da classe Funcionario e popule suas propriedades:
Crie uma lista de Funcionários, inicializando-a com esses objetos:
29/03/2015LINQ via C# - .Net Coders 28
GroupBy (com e sem o método de extensão)
Selecionamos os salários de funcionários em ordem crescente (default)
Quando é ordem crescente não é necessário escrever ascending
Em ordem decrescente: orderby (expressão) descending
29/03/2015LINQ via C# - .Net Coders 29
Aplicando o LIKE do SQL
Selecionar funcionárias que contenham “ita” no nome
29/03/2015LINQ via C# - .Net Coders 30
Agrupar funcionários por departamento
group (elementos) by (chave de agrupamento) into (variável de agrupamento)
Faça uma projeção definindo um tipo anônimo para retornar os dados filtrados (select new)
No exemplo será impresso o departamento e o total de funcionários por depto.
29/03/2015LINQ via C# - .Net Coders 31
Agrupar funcionários por departamento
group (elementos) by (chave de agrupamento) into (variável de agrupamento)
Faça uma projeção definindo um tipo anônimo para retornar os dados filtrados (select new)
No exemplo será impresso o departamento e o total de funcionários por depto.
29/03/2015LINQ via C# - .Net Coders 32
Exemplo de uma consulta sem LINQ
Exemplo de uma consulta com LINQ
29/03/2015LINQ via C# - .Net Coders 33
Nessa parte iremos demonstrar como utilizar consultas LINQ para manipular uma base de dados SQL Server.
Para isso, tenha instalado o SQL Server Management Studio 2008 ou superior.
29/03/2015LINQ via C# - .Net Coders 34
Estudo de caso: Apresentar em um gridview todos os filmes cadastrados em uma locadora
Conecte ao SQL Server;
Criação da Base de Dados
No Object Explorer, clique com o botão direito sobre a pasta Databases e escolha “New Database”
Caso não esteja visível, no Menu acima clique em View e depois escolhe a opção Object Explorer
Em Database Name digite: ProducoesArtisticas e depois confirme.
Selecione agora o banco ProducoesArtisticas, expanda-o no nível de pastas, e selecione a pasta Tables. Com o botão direito, clique em “New Table”
Crie a tabela “Filmes” com os campos FilmeID (int), Nome (varchar (50)), Ano (datetime), Preço (decimal (10,2)), Genero (varchar(15)).
Crie a tabela “Atores” com os campos AtorID (int), FilmeID (int), Nome (varchar (40))
Defina a chave primária de cada tabela: Filmes: FilmeID / Atores: AtorID (Set Primary Key...)
29/03/2015LINQ via C# - .Net Coders 35
Defina o incremento automático de inserção de registros na tabela
A cada registro inserido, o ID será incrementado de 1 em 1 ou conforme for editado em “Identity Increment”
29/03/2015LINQ via C# - .Net Coders 36
Relacionamento entre tabelas
Pode ser feito via diagrama relacional ou manualmente por uma query
Via diagrama relacional:
Na pasta Database Diagrams, confirme a criação de um novo diagrama
Selecione as duas tabelas e clique em Add
Faça a ligação entre as duas tabelas, puxando uma seta do campo FilmeID da tabela Filmes para o campo FilmeID da tabela Atores.
Feito isso, abrirá uma janela “Tables and Columns”. Defina o nome do relacionamento como FK_Atores_Filmes (atores que participaram de um filme).
Primary Key table: Filmes / Foreign Key table: Atores (campos FilmeID)
Via query: (cria-se uma referência de Filme na tabela de Atores)
29/03/2015LINQ via C# - .Net Coders 37
Crie um projeto do tipo Console Application com o nome: NetCoders.LINQtoSQL.Intro;
Abra a janela Server Explorer (Menu -> View -> Server Explorer) para configurar a conexão com o banco;
Com o botão direito clique em Data Connections -> Add Connection;
Mude o Data Source de “Microsoft SQL Server Database File (SqlClient)” para “Microsoft SQL Server”;
Escolha o seu servidor e a opção de login (Windows Authentication ou SQL Server Authentication);
Selecione o banco de dados ProducoesArtisticas;
Concluído o processo de configuração, a sua conexão deverá estar visível em Data Connections.
29/03/2015LINQ via C# - .Net Coders 38
Inserção de registros: pode ser via SQL Server ou pelo Visual Studio
Via SQL Server:
Popule a tabela de Filmes, depois a tabela de Atores:
Filmes
29/03/2015LINQ via C# - .Net Coders 39
Atores
Verificar na tabela de Filmes qual é o ID do Filme no qual esse ator esteve presente
Exemplo: Robbie Williams – Uma Noite no Museu 3 (FilmeID = 3)
Tom Cruise – Mission Impossible (FilmeID = 4), etc...
29/03/2015LINQ via C# - .Net Coders 40
Fazendo a junção (join) entre as tabelas Filmes e Atores, é possível reunir esta informação:
E o resultado será este:
29/03/2015LINQ via C# - .Net Coders 41
As classes DataContext definidos no namespace System.Linq implementam os métodos que permitem a aplicação interagir com os dados salvos no banco;
Essas classes podem ser automaticamente geradas pelo Visual Studio:
No Solution Explorer, clique com o botão direito sobre o projeto
Escolha a opção Add New Item e depois “LINQ to SQL Classes”
Guarde o modelo como ProducoesArtisticas
Arraste as tabelas do Server Explorer para a tela do desenho do modelo de dados, para obter um diagrama como esse:
29/03/2015LINQ via C# - .Net Coders 42
A partir do momento em que arrastamos as tabelas o Visual Studio realiza o mapeamento do banco de dados para a aplicação automaticamente
Verifique o código mapeado em ProducoesArtisticas.designer.cs
Fazer uma consulta LINQ acessando a base de dados SQL Server:
Instancie o modelo:
Agrupar os filmes por gênero
29/03/2015LINQ via C# - .Net Coders 43
Como resultado, percebe-se que as aplicações Console nem sempre são as melhores para a apresentação de dados para o usuário;
Então, crie um projeto Windows Forms com o nome: NetCoders.LINQtoSQL
Set as Startup Project...
Repita o mesmo procedimento dos slides anteriores para mapear o BD na aplicação
No Form1.cs[Design], arraste um DataGridView da ToolBox;
Name: dgFilmes
Form1_Load: duplo clique no form para gerar este evento
Neste evento, quando a aplicação for carregada, ela carregará o grid populado com os dados do banco
29/03/2015LINQ via C# - .Net Coders 44
Form1_Load:
Criação das colunas do grid
Instanciar o contexto
Aplicar a query: selecionar todos os filmes cadastrados
29/03/2015LINQ via C# - .Net Coders 45
Form1_Load:
Cria uma variável idLinha que representa cada linha na tabela
Dentro do foreach, preenchemos a tabela:
29/03/2015LINQ via C# - .Net Coders 46
Fazer uma consulta LINQ to SQL com que realize uma junção das tabelas Atores e Filmes
Selecionar atores que tenham participado de algum filme
Modifique o foreach para imprimir o nome do ator e o nome do filme:
29/03/2015LINQ via C# - .Net Coders 48
Fazer uma consulta LINQ to SQL com que realize uma junção das tabelas Atores e Filmes
Modifique as colunas..
Resultado:
29/03/2015LINQ via C# - .Net Coders 49
Um LINQ Provider é uma implementação do “padrão LINQ” para uma fonte de dados específica;
O padrão LINQ define um conjunto de regras que explicita como os comandos LINQ são mapeados em invocações de métodos de um determinado tipo.
Nem sempre o próprio tipo introduz esses métodos; eles são definidos por meio de um Provider adaptado a implementar os métodos de extensão.
Ao longo dessa palestra, apresentamos o LINQ to Objects, com o qual é possível fazer consultas a coleções de dados em memória; e o LINQ to SQL, para fazer consulta a uma base de dados SQL.
29/03/2015LINQ via C# - .Net Coders 50
Ponto de partida: a interface IEnumerable<T>
Ela fornece o método GetEnumerator() que permite a iteração entre os elementos de uma coleção.
Estratégias para expandir o LINQ para outras fontes de dados não mapeadas pelo .Net:
Adaptar uma API existente, definindo novas classes que podem ser usadas com os Providers LINQ existentes
Criar um novo conjunto de classes para permitir a reutilização dos métodos de extensão
Escrever um Provider LINQ capaz de trabalhar com árvores de expressões
Utilizado para converter código LINQ para outra linguagem
Outra estratégia é escrever em determinada classe novos métodos de extensão que realizam operações auxiliares (mais simples).
29/03/2015LINQ via C# - .Net Coders 52
Um LINQ Provider deve implementar métodos como Select, Where, Join, OrderBy(dentre outros) em uma classe genérica.
29/03/2015LINQ via C# - .Net Coders 53
Vantagens Sintaxe unificada de acesso a dados (desde que haja um provider que implemente o padrão
LINQ sobre essa fonte de dados);
Utilização simultânea de vários Providers: uma mesma expressão pode ter dados de várias fontes de dados;
Consultas fortemente tipadas: todas as expressões são compiladas, assim todos os possíveis erros são detectados em tempo de compilação;
Fácil extensão: caso queira uma nova fonte de dados interagir com LINQ, basta implementar um provider com os métodos definidos pelo LINQ;
Padronização, código limpo e de fácil manutenção
29/03/2015LINQ via C# - .Net Coders 39