 Curso Entity 
Framework 
- 
Consultas Projeção - XI
Curso Entity 
Framework 
- 
Consultas Projeção - XI
|  | Nesta aula vamos abordar as consultas projeção no Entity Framework.(aula anterior) | 
Nesta aula iremos abordar o LINQ-to-Entities e o recurso Projeção (Projection). Para acompanhar a aula você deve ter um conhecimento básico de LINQ.
A LINQ - Language integrated Query - é um conjunto de recursos introduzidos no .NET Framework 3.5 que permitem a realização de consultas diretamente em base de dados , documentos XML , estrutura de dados , coleção de objetos ,etc. usando uma sintaxe parecida com a linguagem SQL.
Ao usar 
aplicativos executados localmente, em alguns cenários, você pode revisar as 
consultas para refinar ainda mais a quantidade de dados retornada do banco de 
dados. Uma técnica a ser considerada é o uso de projeções, que permite a você 
muito mais controle sobre quais dados relacionados são retornados. 
Nem o Eager Loading(carregamento imediato), nem o
Lazy Loading(carregamento deferido/lento) no Entity 
Framework permitem que você filtre ou classifique os dados relacionados que 
estão sendo retornados. Porém, em uma projeção, você pode fazer isso. (
http://msdn.microsoft.com/pt-br/magazine/gg309181.aspx )
A projeção é um processo de seleção de dados em um formato diferente, em vez de consultar uma entidade específica. Há muitas maneiras de projeção. Vamos ver agora alguns estilos de projeção:
recursos usados :
Preparando o ambiente
Crie uma novo solução no VS 2013 Express for Windows desktop com o nome EF6_EscolaDB
No menu File clique em Add -> New Project e inclua um projeto do tipo Class Library com o mesmo nome da solução;
A seguir inclua um Entity Data Model no menu PROJET -> Add New Item selecionando o template ADO .NET Entity Data Model e informando o nome EscolaDB.edmx selecionando todas as tabelas do banco de dados EscolaDB.mdf.
Nota: O ambiente e o banco de dados EscolaDB.mdf forma definidos nas aulas 1 , 2 e 3.
Dessa forma teremos criado um contexto chamado EscolaDBEntities que iremos usar para acessar as entidades e realizar as consultas.
Após isso inclua um novo projeto do tipo Console Application com o nome Consultas_Projecao na solução;
Para concluir inclua uma referência ao projeto Consultas_Projecao para o projeto EF6_EscolaDB, inclua a string de conexão no arquivo App.Config do projeto template e inclua uma referência ao Entity Framework no projeto.
1- First ou FirstOrDefault
Se você deseja obter um único objeto, como um aluno por exemplo, quando existem muitos alunos com o mesmo nome no banco de dados, você pode usar First ou FirstOrDefault:
Exemplo:
|    using(var ctx = new EscolaDBEntities())
   {       //Exibe o SQL gerado na janela Debug      
       ctx.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);             var aluno = (from a in ctx.Alunos
                                where a.AlunoNome == "Janice"
                                select a).FirstOrDefault<Aluno>();              Console.WriteLine(aluno.AlunoNome.ToString());
              Console.ReadKey();
  } |     SELECT TOP (1) 
    [Extent1].[AlunoId] AS [AlunoId], 
    [Extent1].[AlunoNome] AS [AlunoNome], 
    [Extent1].[PadraoId] AS [PadraoId]
    FROM [dbo].[Aluno] AS [Extent1]
    WHERE N'Janice' = [Extent1].[AlunoNome]
 | 
A consulta localiza um aluno cujo nome seja igual a 'Janice'. Com FirstOrDefault() será localizada a primeira ocorrência.
A diferença entre First e FIrstOrDefault é que First() irá lançar uma exceção se não existir dados para o critério informado ao passo que FirstOrDefault retorna o valor padrão (null) se não existir dados.
2- Single ou SingleOrDefault
Podemos usar também Single ou SingleOrDefault para obter um único objeto, por exemplo aluno com o nome igual a 'Janice', quando não existirem mais de um objeto:
Exemplo:
|    using(var ctx = new EscolaDBEntities())
   {       //Exibe o SQL gerado na janela Debug      
       ctx.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);             var aluno = (from a in ctx.Alunos
                                where a.AlunoNome == "Janice"
                                select a).SingleOrDefault<Aluno>();              Console.WriteLine(aluno.AlunoNome.ToString());
              Console.ReadKey();
  } |     SELECT TOP (2) 
    [Extent1].[AlunoId] AS [AlunoId], 
    [Extent1].[AlunoNome] AS [AlunoNome], 
    [Extent1].[PadraoId] AS [PadraoId]
    FROM [dbo].[Aluno] AS [Extent1]
    WHERE N'Janice' = [Extent1].[AlunoNome]
 | 
Tanto SingleOrDefault como Single irão lançar uma exceção, se o resultado contiver mais de um elemento. Use Single ou SingleOrDefault onde você tem certeza que o resultado irá conter apenas um elemento. Se o resultado tem vários elementos, então deve haver algum problema.
3 - ToListSe você deseja listar todos os alunos cujo nome é 'Janice' então use ToList():
|    using(var ctx = new EscolaDBEntities())
   {       //Exibe o SQL gerado na janela Debug      
       ctx.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);             var aluno = (from a in ctx.Alunos
                                where a.AlunoNome == "Janice"
                                select a).ToList<Aluno>();              Console.ReadKey();
  } |         SELECT 
    [Extent1].[AlunoId] AS [AlunoId], 
    [Extent1].[AlunoNome] AS [AlunoNome], 
    [Extent1].[PadraoId] AS [PadraoId]
    FROM [dbo].[Aluno] AS [Extent1]
    WHERE N'Janice' = [Extent1].[AlunoNome]
 | 
4 - Group By
|    using(var ctx = new EscolaDBEntities())
   {       //Exibe o SQL gerado na janela Debug      
       ctx.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);         var aluno = from a in ctx.Alunos
                         group a by a.AlunoId into AlunoGrupoId
                         select AlunoGrupoId;         Console.WriteLine(aluno);
         Console.ReadKey();
  } |         
 | 
5 - OrderBy
|    using(var ctx = new EscolaDBEntities())
   {       //Exibe o SQL gerado na janela Debug      
       ctx.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);       var aluno = from a in ctx.Alunos
                            orderby a.AlunoNome ascending
                            select a; ;        Console.ReadKey();
  } |         
 | 
Usando classes anônimas para filtrar informações
Podemos usar o recurso das classes anônimas para criar projeções selecionando dados.
Os tipos anônimos fornecem uma maneira conveniente para encapsular um conjunto de propriedades somente leitura em um único objeto sem precisar primeiro definir explicitamente um tipo.
O nome do tipo é gerado pelo compilador e não está disponível no nível do código fonte. O tipo das propriedades é inferido pelo compilador.
Exemplo:
|    using(var ctx = new EscolaDBEntities())
   {       //Exibe o SQL gerado na janela Debug      
       ctx.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);         var resultado = from a in ctx.Alunos
                                   where a.AlunoNome == "Macoratti"
                                  select new
                                  {
                                       a.AlunoId,
                                       a.AlunoEndereco,
                                       a.Cursos
                                  };        Console.ReadKey();
  } |     
 | 
Na consulta acima usamos uma classe anônima (Select New) para selecionar o Id, Endereço e os cursos do aluno com nome igual a 'Macoratti'.
O tipo anônimo possui 3 propriedades : AlunoId, AlunoEndereco e Cursos.
Executando consultas aninhadas
Quando você escreve uma consulta, em qualquer lugar em um valor que é esperado você pode usar outra consulta em seu lugar, desde que essa consulta retorne um tipo aceitável. Você pode usar uma consulta aninhada no lugar de uma expressão ou uma coleção.
Exemplo:
|    using(var ctx = new EscolaDBEntities())
   {       //Exibe o SQL gerado na janela Debug      
       ctx.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);      var consulta = from a in ctx.Alunos
                                   from c in a.Cursos
                                   where a.PadraoId == 1
                                   select new
                                   {
                                       a.AlunoNome, c
                                   };var resultado = consulta.ToList(); Console.WriteLine(resultado);         Console.ReadKey();
  } | SELECT 
[Extent1].[AlunoId] AS [AlunoId], 
[Extent1].[AlunoNome] AS [AlunoNome], 
[Join1].[CursoId1] AS [CursoId], 
[Join1].[CursoNome] AS [CursoNome], 
[Join1].[CursoLocalizacao] AS [CursoLocalizacao], 
[Join1].[ProfessorId] AS [ProfessorId]
FROM [dbo].[Aluno] AS [Extent1]
INNER JOIN (SELECT [Extent2].[AlunoId] AS [AlunoId], [Extent3].[CursoId] AS [CursoId1], [Extent3].[CursoNome] AS [CursoNome],
 [Extent3].[CursoLocalizacao] AS [CursoLocalizacao], [Extent3].[ProfessorId] AS [ProfessorId]
FROM [dbo].[AlunoCurso] AS [Extent2]
INNER JOIN [dbo].[Curso] AS [Extent3] ON [Extent3].[CursoId] = [Extent2].[CursoId] ) AS [Join1] ON [Extent1].[AlunoId] = [Join1].[AlunoId]
WHERE 1 = [Extent1].[PadraoId]
        
 | 
Neste exemplo estamos realizando duas consultas aninhadas consultando Alunos e Cursos. O resultado será uma lista anônima com objetos Alunos e Cursos.
Vimos assim algumas projeções mais básicas e usadas com LINQ.
Na próxima aula vamos tratar do Eager Loading no Entity Framework.
Rogo-vos, pois, eu, o preso do Senhor, 
que andeis como é digno da vocação com que fostes chamados, 
Com toda a humildade e mansidão, com longanimidade, suportando-vos uns aos 
outros em amor, 
Procurando guardar a unidade do Espírito pelo vínculo da paz.
Efésios 4:1-3
| Veja os 
    Destaques e novidades do SUPER DVD Visual Basic 
(sempre atualizado) : clique e confira ! Quer migrar para o VB .NET ? 
 Quer aprender C# ?? 
 | 
             Gostou ?
  Compartilhe no Facebook
Compartilhe no Facebook
  
 Compartilhe no Twitter
 
Compartilhe no Twitter
 
Referências: