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.

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:

  1. First : Retorna o primeiro elemento da seqüência.
  2. FirstOrDefault : Retorna o primeiro elemento da seqüência, ou o valor padrão se a seqüência esta vazia.

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]

 

 
No código acima a linha de código :
  ctx.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);   exibe o SQL gerado na janela de saída Debug;

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:

  1. Single - Retorna o único elemento de um seqüência única.
  2. SingleOrDefault -     Retorna o único elemento de uma seqüência , ou valor padrão se estiver vazia.

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 - ToList

Se você deseja listar todos os alunos cujo nome é 'Janice' então use ToList():

  1. ToList - Percorre uma seqüência, capturando os resultados em uma List<T>.
   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

  1. Group By - Agrupa os elementos de uma seqüência pela chave
   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 Twitter
 

Referências:


José Carlos Macoratti