EF 6 - Aplicação em Camadas - Entendendo o código do repositório - IV


 Neste artigo vamos continuar o nosso exemplo anterior explicando em detalhes a implementação da interface IRepositorio.

Entendendo o código usado na implementação do repositório

No artigo anterior definimos a interface do nosso repositório e fizemos sua implementação na classe Repositorio.

O que é uma interface ?

Uma interface, no paradigma da orientação a objetos, é  um tipo de classe que contém apenas as assinaturas de métodos, propriedades, eventos e indexadores.

A implementação dos membros é feita por uma classe concreta ou struct que implementa a interface.

Segue abaixo novamente o código da classe Repositorio implementando a interface IRepositorio e a interface IDisposable:

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;

namespace DAL
{
    public class Repositorio<T> : IRepositorio<T> , IDisposable where T : class
    {
        private CadastroEntities Context;

        protected Repositorio()
        {
            Context = new CadastroEntities();
        }

        public IQueryable<T> GetTodos()
        {
            return Context.Set<T>();
        }

        public IQueryable<T> Get(Expression<Func<T, bool>> predicate)
        {
            return  return Context.Set<T>().Where(predicate);
        }

        public T Find(params object[] key)
        {
            return Context.Set<T>().Find(key);
        }

        public T First(Expression<Func<T, bool>> predicate)
        {
            return Context.Set<T>().Where(predicate).FirstOrDefault();
        }

        public void Adicionar(T entity)
        {
            Context.Set<T>().Add(entity);
        }

        public void Atualizar(T entity)
        {
            Context.Entry(entity).State = EntityState.Modified;
        }

        public void Deletar(Func<T, bool> predicate)
        {
            Context.Set<T>()
           .Where(predicate).ToList()
           .ForEach(del => Context.Set<T>().Remove(del));
        }

        public void Commit()
        {
            Context.SaveChanges();
        }

        public void Dispose()
        {
            if (Context != null)
            {
                Context.Dispose();
            }
                GC.SuppressFinalize(this);
            }
        }
}

Agora vamos detalhar e entender cada método implementado.

1-   private CadastroEntities Context;

     protected Repositorio()
     {
            Context = new CadastroEntities();
     }

Aqui estamos referenciando o contexto representando por CadastroEntities na variável Context e criando uma nova instância do contexto. Tudo depende do contexto e vamos usar sua referência em todos os métodos para acessar as entidades no Entity Data Model.

2-  public IQueryable<T> GetTodos()
     {
           return Context.Set<T>();
     }

O método GetTodos() recebe uma entidade (uma classe) e retorna um IQueryable,  ou seja uma lista completa das entidades. (Aqui o método Set<T> do contexto retorna uma instância instância DbSet<T> para o acesso a entidades de determinado tipo no contexto.)

Para entender melhor o IQueryable veja o meu artigo :  .NET - Comparando IEnumerable com IQueryable.

3-  public IQueryable<T> Get(Expression<Func<T, bool>> predicate)
     {
          return  return Context.Set<T>().Where(predicate);
     }

O método Get() usa um delegate Func<> como parâmetro de entrada, onde será usada uma expressão lambda (Ex: p => p.EmpregadoId == ID) como critério, e, um predicate para validar o critério usando a cláusula Where. O retorno será uma lista IQueryable.

Para entender melhor o delegate Func<> veja o meu artigo: C# - Apresentando o delegate Func

4- public T Find(params object[] key)
    {
       return Context.Set<T>().Find(key);
    }

O método Find() realiza uma busca pela chave primária. O parâmetro de entrada é um array de objetos. O método localiza uma entidade com os valores indicados na chave primária.

Se a entidade existir no contexto, então ela é devolvida imediatamente. Caso contrário, é feita uma solicitação à base. Se nenhuma entidade for encontrada no contexto ou na base, então é retornado null.

5- public T First(Expression<Func<T, bool>> predicate)
    {
        return Context.Set<T>().Where(predicate).FirstOrDefault();
    }

O método First() usa uma expressão com o delegate Func<> como entrada, aqui usaremos uma expressão lambda que será validada pelo predicate usando a cláusula Where. FirstOrDefault() garante que será retornado o primeiro elemento da seqüência que satisfaça a condição definida na expressão lambda ou o valor padrão se nenhum elemento for encontrado.

6- public void Adicionar(T entity)
    {
          Context.Set<T>().Add(entity);
    }

O método Adicionar() recebe uma entidade e usando o método Add() do contexto inclui a entidade no contexto. (Nos bastidores o EF cria uma instrução SQL Insert)

Você pode incluir diversas entidades de uma vez. Apenas lembre-se que neste cenário estamos trabalhando na memória. Para persistir no banco de dados devemos o método SaveChanges().

7- public void Atualizar(T entity)
    {
        Context.Entry(entity).State = EntityState.Modified;
    }

O método Atualizar() recebe uma entidade e define o seu EntityState como Modified informando ao contexto que a entidade foi alterada.

O estado da entidade é uma enumeração do tipo System.Data.EntityState que declara os seguintes valores:

  1. Added - A entidade é marcada como adicionada;
  2. Deleted - A entidade é marcada como deletada;
  3. Modified - A entidade foi modificada;
  4. Unchanged - A entidade não foi modificada;
  5. Detached - A entidade não esta sendo tratada no contexto;   

O contexto não só trata a referência para todos os objetos recuperados do banco de dados, mas também detém os estados da entidade e mantém as modificações feitas nas propriedades da entidade. Este recurso é conhecido como controle de alterações ou Change Tracking.

A mudança no estado da entidade de Unchanged para o estado Modified é o único estado que é feito automaticamente pelo contexto.

8- public void Deletar(Func<T, bool> predicate)
    {
        Context.Set<T>()
       .Where(predicate).ToList()
       .ForEach(del => Context.Set<T>().Remove(del));
    }

O método Deletar() usa como parâmetro de entrada um delegate Func<>, onde será usada uma expressão lambda, que será validada pelo predicate usando a cláusula Where(). Note que estamos usando o método Remove do contexto com uma expressão lambda (del => Context.Set<T>().Remove(del)) em um .ForEach(), o efeito disso é que ele irá varrer a lista retornada e irá remover todos os itens que atendem ao critério definido para remoção.

9- public void Commit()
    {
            Context.SaveChanges();
    }

O método Commit() é um dos mais importantes porque ele usa o método SaveChanges() do contexto para persistir no banco de dados as inclusões, exclusões e alterações feitas no contexto que ainda estão na memória.

Quando você trabalha com o Contexto e seus métodos esta trabalhando na memória. O método SaveChanges() efetiva todas as operações gravando-as no banco de dados. Assim quando você trabalha na memória pode ter muitas entidades em diversos estados, e quando usa o SaveChanges() elas serão efetivamente gravadas no banco de dados.

10- public void Dispose()
     {
           if (Context != null)
           {
                Context.Dispose();
            }
            GC.SuppressFinalize(this);
     }

O método Dispose() implementa a interface IDisposable e verifica se o contexto não é nulo para liberar recursos usados

Os conceitos sobre Delegates (Func, Action, Predicate)  e Expressões Lambdas são a base para entender o código usado na implementação feita.

Na próxima parte do artigo vamos definir a nossa camada de negócios.

 Porque não vos fizemos saber a virtude e a vinda de nosso Senhor Jesus Cristo, seguindo fábulas artificialmente compostas; mas nós mesmos vimos a sua majestade. (2 Pedro 1:16)

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

  Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Referências:


José Carlos Macoratti