Você está na página 1de 31

05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

Repositório de Dados no Entity


Framework 6
24/04/2014 • 27 minutos para ler
Neste artigo
Renato Haddad
Março, 2014
Solução Repositório
Contexto
Interface da Classe
Classe Repositório de Cliente
Projeto de Console Application
Projeto ASP.NET MVC 5
Controller de Clientes
Ajustes no Controller
Views (UI interface de usuário)
Conclusão
Sobre o Autor

Renato Haddad 

Março, 2014
O objetivo deste artigo é ilustrar como criar um Repositório de Dados no Entity
Framework 6 com classes em Visual C# 5. O uso de repositório é antigo, diversas
tecnologias usam, e pesquisando na internet encontrei diversos exemplos pobres em
funcionalidades, muitas vezes alguns que torna o trabalho do desenvolvedor muito
braçal, e ao longo do projeto, compromete a produtividade. Sendo assim, ao longo de
anos do EF e algumas conversas com o Rowan Miller, Program Manager do EF na
MS/EUA, resolvi escrever este artigo para ajuda-los a montar uma arquitetura genérica
de repositório de dados.

https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 1/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

Em alguns momentos críticos de um projeto, uma decisão de qual caminho seguir é


fundamental. Isto vale para qualquer tipo de projeto, e em TI vale desde uma simples
planilha no Excel até projetos complexos de E-Commerce. E, quando adicionamos o uso
de banco de dados, projeto em equipes (centralizadas ou não), começa a ficar crítico.
Isto sem falar em outras variáveis como extensibilidade, camadas de dados,
persistência, outras plataformas, etc. Enfim, o projeto que irei criar será uma solução
com diversos projetos separados, a fim de focar em cada camada.

Os pré-requisitos para este artigo são conhecimento intermediário de C# e o Visual


Studio .NET 2013.

Solução Repositório
A primeira coisa a fazer é criar uma solução vazia. Para isto, abra o Visual Studio 2013,
selecione a opção File / New / Project ou CTRL + SHIFT + N ou na janela inicial, clique
em New Project. Conforme a figura 1, selecione Other Project Types / Visual Studio
Solutions. Em Name digite Repositorio.MSDN e no Location você pode gravar onde
desejar.

Figura 1 – Nova solução

Clique no botão OK e note no Solution Explorer que existe apenas a solução vazia.
Quando falamos de repositório de dados, a primeira coisa que pensamos são as
entidades, ou seja, a estrutura das classes, o que normalmente serão espelhadas em
tabelas no banco de dados. Aqui, você pode abstrair diretamente do banco de dados
utilizando o recurso do Model First do Entity Framework ou usar o fantástico recurso de

https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 2/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

Code First. Mas, se neste projeto pretendo ter somente as entidades, não é certo pensar
que a string de conexão com o banco de dados estará neste projeto. E, é verdade, neste
projeto de DLL (Class Library) não teremos nada referente ao local onde as entidades
estão armazenadas. Para isto, criarei um projeto de DAL (Data Access Layer), o qual
usará as entidades que criaremos aqui.

Sendo assim, no Solution Explorer, clique com o botão direito e selecione Add / New
Project. Conforme a figura 2, selecione a linguagem Visual C# e o template Class
Library. Em Name digite Repositorio.Entidades e o Location deixe como está.

Figura 2 – Projeto de entidades

Clique no botão OK e deixe que o Visual Studio crie o projeto. Como é um projeto de
Class Library, o VS já cria uma classe chamada Class1, portanto, exclua-a. Em seguida,
crie uma classe (Add/Class) chamada Cliente, conforme a estrutura a seguir.
Basicamente é uma classe pública contendo as propriedades do objeto Cliente. Nem
preciso dizer que você pode adicionar ou remover propriedades conforme a
necessidade.

C# = Copiar

namespace Repositorio.Entidades
{
public class Cliente
{
public int ClienteID { get; set; }
public string Nome { get; set; }
public string CNPJ { get; set; }
public string Endereco { get; set; }
https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 3/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

public string Telefone { get; set; }


public bool Ativo { get; set; }
}
}

Pergunta: Qual propriedade é a chave primária? No Entity Framework 6 se uma


propriedade contém o nome da classe seguido de ID, esta será a chave primária. No
caso da classe Cliente, a propriedade ClienteID será a chave. E, se eu quiser colocar
outro nome, por exemplo ChaveCliente ou apenas ID? Aí você terá que usar o Data
Annotations e informar o atributo [Key] para a respectiva propriedade.

Pronto, salve a classe e compile o projeto F6. Se houver algum erro nesta classe, corrija
porque é necessário que o projeto esteja compilado 100% com sucesso.

O próximo passo é criar um novo projeto chamado Repositorio.DAL, o qual será o


responsável por manipular a classe cliente criada. Sendo assim, no Solution Explorer,
Add / New Project, escolha o template de Class Library. Em Name digite
Repositorio.DAL e clique no botão OK, conforme a figura 3.

Figura 3 – Projeto de DAL

Da mesma forma que o projeto anterior, exclua a Class1.cs criada automaticamente. O


primeiro passo é adicionar as referências necessárias. Vamos utilizar o fantástico recurso
do Nuget para esta tarefa, portanto, selecione o menu Tools / Library Package Manager
/ Package Manager Console. Conforme a figura 4, será aberta a janela do Nuget, então
na combobox Default project, selecione Repositorio.DAL, afinal temos dois projetos. Em
seguida digite:

https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 4/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

Install-Package EntityFramework

Figura 4 – Instalação do EF via Nuget

Desta forma o EF será instalado apenas neste projeto. Note ainda que a versão
instalada é a 6.0.2, fato que é a mais recente no mercado no momento em que estou
escrevendo este artigo. Não se assuste se for instalada uma versão superior do EF
quando você for simular estes códigos.

Em seguida, no projeto Repositorio.DAL, clique com o botão direito em References no


Solution Explorer, selecione Add Reference. Na janela aberta, selecione Assemblies,
localize o namespace System.Data.Entity, conforme a figura 5. Ao final, clique no botão
OK.

Figura 5 – Adicionar referências do namespace

https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 5/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

Repita o mesmo passo, mas referencie o projeto Repositorio.Entidades, conforme a


figura 6, afinal o DAL irá gerenciar as entidades.

Figura 6 – Adicionar referências do projeto de entidades

Contexto
Excelente, já temos todas as referências necessárias. Pressione F6 para compilar com
sucesso. Em seguida, por uma questão de estrutura e organização, crie as pastas
Contexto, Repositorios e Base, sendo que a Base é dentro de Repositorios. Na pasta
Contexto, crie uma nova classe chamada BancoContexto.cs. Adicione os seguintes
namespaces:

C# = Copiar

using System.Data.Entity;
using Repositorio.Entidades;

Esta será a classe de contexto, portanto, para que ela gerencie toda a parte de banco de
dados (criar, excluir e gerenciar o DB) é preciso herda-la de DbContext. Sendo assim, na
assinatura da classe, adicione o : DbContext.

Em seguida, precisamos informar qual será a string de conexão, afinal o banco ainda
não existe, e mesmo que existisse, em algum lugar deverá estar o caminho completo da
conexão, certo? Sendo assim, no construtor desta classe, adicione o : base(“chave”),
sendo que a chave é exatamente o caminho da conexão que está descrito no arquivo
App.Config ou Web.Config (se for ASP.NET). Mas atenção: no projeto Repositorio.DAL
você NÃO deverá incluir esta chave no App.Config. Eu disse que a chave deverá constar
apenas no projeto que irá solicitar o DAL.

https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 6/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

Por default, chamei a chave de ConnDB e mantenha este nome para que possamos
definir o padrão. Muitos chamam de strConn ou stringConexao ou ConexaoBanco,
enfim, o importante é que você defina o seu padrão e passe para todos os projetos que
a utilizarão.

Dica: o ConnDB não pode ser dinâmico? Sim, isto não é nenhum problema pois se você
analisar o construtor do DbContext irá notar que há várias sobrecargas, as quais você
pode construir o código para ser uma chave dinâmica.

Veja como está a classe até o momento:

C# = Copiar

using System.Data.Entity;
using Repositorio.Entidades;

namespace Repositorio.DAL.Contexto
{
public class BancoContexto : DbContext
{
public BancoContexto() : base("ConnDB") { }

}
}

Pressione F6 para compilar e certifique-se que está 100% com sucesso.

Interface da Classe
O que é uma interface de uma classe? Entendemos que interface é um contrato de
como uma classe deve ser implementada, contendo todas as ações definidas, não as
implementações de códigos de comportamentos. Um exemplo bem clássico é o famoso
contrato de aluguel, o qual são definidos na interface (contrato padrão), os nomes do
inquilino e proprietário, data de pagamento, multas, imóvel, etc. E, quando se redige o
contrato do aluguel é que teremos os dados preenchidos em si.

No nosso caso, vamos criar na pasta Base uma interface chamada IRepositorio.cs,
contendo todos os métodos que deverão ser implementados pela classe que usar esta
interface como referência. Logo de cara, não se assuste com a assinatura da classe.
Existe o TEntity declarado, assim como quem é, ou seja, neste caso TEntity é uma class.
Veja o código a seguir.

C# = Copiar

using System;
using System.Collections.Generic;
https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 7/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Repositorio.DAL.Repositorios.Base
{
interface IRepositorio<TEntity> where TEntity : class
{
IQueryable<TEntity> GetAll();
IQueryable<TEntity> Get(Func<TEntity, bool> predicate);
TEntity Find(params object[] key);
void Atualizar(TEntity obj);
void SalvarTodos();
void Adicionar(TEntity obj);
void Excluir(Func<TEntity, bool> predicate);
}
}

Veja uma descrição detalhada dos métodos da interface para um melhor entendimento.

Retorna todos os dados como IQueryable, ou seja, você pode


IQueryable<TEntity> retornar a lista e aplicar expressões Lambda para filtrar e
GetAll(); classificar dados, por exemplo.

IQueryable<TEntity> Retona todos os dados que atenderem a um critério passado em


Get(Func<TEntity, tempo de execução através de uma expressão Lambda. Neste caso,
bool> predicate); o Func é um delegate que será criado dinâmicamente, aplica-se o
predicate para verificar se o dado atende ao critério. Aqui eu sei
que dará um nó na cabeça, mas é preciso um conhecimento de C#
avançado, então, pesquise sobre Delegates, Func e predicate.

TEntity Find(params Irá aplicar um filtro pela chave primária da classe em si. Quem é a
object[] key); chave primária? Não importa porque o Find recebe um array de
object e efetua a pesquisa. Com isto, se você tiver uma chave
composta, o Find se encarrega de tudo, basta você passar os dados
e pronto.

void Atualizar(TEntity Recebe o objeto TEntity para efetuar o Update no banco.


obj);

void SalvarTodos(); Chama o método SaveChanges para efetivar todas as alterações no


contexto.

void Adicionar(TEntity Recebe o objeto TEntity para efetuar o Insert no banco.


obj);

void Este método irá excluir registros, sendo que a condição é dinâmica
Excluir(Func<TEntity, através de uma expressão Lambda e aplica-se o predicate para a
bool> predicate); condição passada.

https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 8/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

Agora que já temos a interface criada, vamos criar e implementar a classe. Portanto, na
pasta Base, adicione uma classe chamada Repositorio. Adicione os seguintes
namespaces:

C# = Copiar

using System.Data.Entity;
using Repositorio.DAL.Contexto;

Veja a classe completa com todas as implementações. Note que a classe é abstract para
que ela não possa ser herdada. Na assinatura TEntity também é uma classe (where
TEntity : class). Note que esta classe herda outras duas interfaces, sendo IDisposable
(para que possa suportar o Dispose) e IRepositorio<TEntity>. Quando você digitar estas
heranças, o Visual Studio coloca uma notação em azul dizendo que não estão
implementadas. Então, basta selecionar as classes (IDisposable e IRepositorio) e dar um
CTRL + . (ponto) duas vezes. Toda a estrutura das interfaces serão criadas nesta classe.

A seguir, para cada método você deverá digitar os códigos de acordo com a
funcionalidade. Uma coisa interessante que você deve estar questionando: como é que
a classe sabe quando serão feitos os selects, updates, deletes e inserts? Pois é meu
amigo, não é mágica não, são códigos dinâmicos que o Entity Framework implementa
com o DbContext e DbSet. Cabe a nós informar a entidade e os critérios, o restante é
com o compilador que irá executar.

Certa ocasião, um aluno me perguntou: Mas Renato, e as instruções T-SQL ou PL-SQL,


onde as escrevo? Eu disse: você não escreverá nenhuma linha disso nunca mais, pois
quem é o responsável em montar toda a instrução é o compilador, tudo agora é
dinâmico. Nem preciso dizer que o olhar de interrogação ficou estampado no rosto da
pessoa. E, você leitor, aprofunde-se nestes códigos para entender e tirar mais proveito
ainda.

C# = Copiar

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Data.Entity;
using Repositorio.DAL.Contexto;

namespace Repositorio.DAL.Repositorios.Base
{
public abstract class Repositorio<TEntity> : IDisposable,
IRepositorio<TEntity> where TEntity : class

https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 9/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

{
BancoContexto ctx = new BancoContexto();
public IQueryable<TEntity> GetAll()
{
return ctx.Set<TEntity>();
}

public IQueryable<TEntity> Get(Func<TEntity, bool> predicate)


{
return GetAll().Where(predicate).AsQueryable();
}

public TEntity Find(params object[] key)


{
return ctx.Set<TEntity>().Find(key);
}

public void Atualizar(TEntity obj)


{
ctx.Entry(obj).State = EntityState.Modified;
}

public void SalvarTodos()


{
ctx.SaveChanges();
}

public void Adicionar(TEntity obj)


{
ctx.Set<TEntity>().Add(obj);
}

public void Excluir(Func<TEntity, bool> predicate)


{
ctx.Set<TEntity>()
.Where(predicate).ToList()
.ForEach(del => ctx.Set<TEntity>().Remove(del));
}

public void Dispose()


{
ctx.Dispose();
}
}
}

Aqui requer uma explicação mais detalhada dos métodos, afinal, a interface
diz o método e a classe é que diz como o código será implementado.

O primeiro é a declaração do BancoContexto, já que tudo depende dele, nada mais


justo que referenciá-lo.

C# = Copiar

https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 10/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

BancoContexto ctx = new BancoContexto();

Já o método GetAll, simplesmente recebe a entidade em si, Cliente por exemplo, e


retorna um IQueryable (lista) completa, um “Select *”.

C# = Copiar

public IQueryable<TEntity> GetAll()


{
return ctx.Set<TEntity>();
}

O método Get é o melhor de todos porque além de ser 100% dinâmico, você usa
expressões Lambda o tempo todo. Sempre digo que todo desenvolvedor DEVE saber
Lambda, pois sem isto não é possível viver de forma produtiva. Este método Get retorna
também uma lista IQueryable, no entanto, o parâmetro de entrada é uma Func da
entidade, Cliente por exemplo, o qual será passado o critério a ser aplicado no
predicate. Nos bastidores, você deverá passar uma expressão Lambda, por exemplo “c
=> c.Nome.Contains("microsoft")”. Já na implementação, é chamado o método GetAll,
explicado anteriomente, e aplica-se o filtro Where com a Lambda recebida na entrada.

C# = Copiar

public IQueryable<TEntity> Get(Func<TEntity, bool> predicate)


{
return GetAll().Where(predicate).AsQueryable();
}

Pergunta: Quantas vezes a classe vai ao banco de dados? Duas correto, pois primeiro
executa o GetAll, vai no banco e retorna todos os dados, e em seguida vai no banco
novamente para aplicar o Where, certo? Errado! A expressão Lambda é montada em
sua árvore de expressões, e no momento em que irá ser usada ou retornada a quem
chamou é que vai ao banco de dados. Neste caso o GetAll será um subterfújio para
aplicar o predicate com o critério, ou seja, irá apenas uma vez ao banco de dados. O
legal aqui é rodar este método com o Profile do SQL ativado para se ver a instrução T-
SQL montada para isto.

O Find busca automaticamente pela chave primária, sendo que a entrada do parâmetro
é um array de object, ou seja, pode ser apenas um campo ou um conjunto que compõe
a chave composta.

C# = Copiar

https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 11/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

public TEntity Find(params object[] key)


{
return ctx.Set<TEntity>().Find(key);
}

O Atualizar recebe a entidade Cliente, por exemplo, e atribui o Modified para o


EntityState, informando ao contexto que tal entidade foi modificada. Atenção: aqui não
é feito nenhum Update no banco, pois quem é o responsável por isto é o SaveChanges
do método Salvar.

C# = Copiar

public void Atualizar(TEntity obj)


{
ctx.Entry(obj).State = EntityState.Modified;
}

O SalvarTodos chama o SaveChanges do contexto e efetiva todas as operações de


Update, Insert ou Delete no banco de dados. O contexto do Entity Framework é uma
forma de manipular dados na memória apenas, nada no banco de dados, portanto,
você pode ter muitas entidades no contexto (até o limite da memória da máquina),
sendo que cada entidade pode ter operações distintas de Update, Delete ou Insert.
Deixe os dados na memória e quando precisar, chame o SaveChanges para efetivar
fisicamente no banco.

Pergunta 1: Posso colocar 300 entidades no mesmo contexto no EF 6? Sim e deve, pois
já fiz testes de performance em relação à quantidade de entidades no mesmo contexto,
e não há nenhum problema de lentidão. Em projetos médios é comum ter muitas
entidades no mesmo contexto, e isto até facilita o gerenciamento, pois basta um
SaveChanges e pronto.

Pergunta 2: Mas não é aconselhável dividir as entidades em diversos contextos? No EF 6


não é preciso, pois o gerencimento do contexto em apenas um facilita muito. Já em
versões anteriores era um problema sério. No EF 4 e 5 tive projetos em diversos
contextos, o que causou um problema sério de união de contextos, transações em
diferentes contextos e atualizações de entidades. Dica: migre urgente para o EF 6, no
mínimo.

C# = Copiar

public void SalvarTodos()


{
ctx.SaveChanges();
}

https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 12/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

O Adicionar recebe a entidade Cliente, por exemplo, e adiciona o registro através do


método Add. Nos bastidores a instrução Insert será criada devidamente correta com
todos os parâmetros declarados para proteger qualquer tentativa de injeção de SQL.

Pergunta 1: Posso incluir diversos objetos de uma vez? Sim e deve. Como tudo estará
no contexto, ou seja na memória, vá incluindo quantos registros quiser em todas as
entidades, e ao final chame o SalvarTodos apenas uma vez.

Pergunta 2: Se eu tiver uma lista de clientes a serem incluídos, preciso adicionar e salvar
cada um? Quando se tem uma lista, você deve aplicar uma Action para disparar o
ForEach a partir da lista, sendo que a Action será o delegate que irá chamar o Adicionar,
passando cada um dos elementos da lista. Ao final de tudo é que chama-se o
SalvarTodos apenas uma vez. Preste atenção mais adiante no projeto de Console, pois
iremos incluir alguns clientes desta forma. E, prepare o balde para babar com o código.
Prometo que os teus loopings nunca mais serão iguais, viva o C# 5!

C# = Copiar

public void Adicionar(TEntity obj)


{
ctx.Set<TEntity>().Add(obj);
}

O Excluir na minha opinião é a melhor funcionalidade de conceitos aplicados até agora.


O parâmetro de entrada é uma expressão Lambda que será usada no predicate. Pense
da seguinte forma: desejo excluir os clientes da cidade=florianópolis ou ativo=false ou
contém o nome=jose, enfim, quem monta a expressão é a situação, pois ela tem que
ser dinâmica para se adequar ao momento. E, ao mesmo tempo, a implementação
deverá atender a TODAS as situações. Sendo assim, o contexto ctx seleciona a entidade
TEntity (cliente, por exemplo), aplica o filtro Where com a condição definida no
predicate (expressão Lambda do parâmetro). Em seguida, é preciso aplicar o ToList para
converter para uma lista. E, aí sim vem a glória do ForEach para varrer toda a lista e
remover todos os itens que atenderem ao critério. Como que isto acontece nos
bastidores? É simples (como se fosse), o compilador irá disparar um delegate para criar
um método em tempo de execução, o qual irá excluir o item da lista. Ou seja, tudo
ocorre em tempo de execução, dinamicamente com delegate.

Pergunta 1: Mas não posso usar o foreach normal ou o for? Sim, pode, mas o código
ficará maior, com mais linhas, porém de fácil manutenção! Isto até que você se
acostume com a sintaxe do ForEach da lista.

Pergunta 2: Posso ter dois métodos Excluir, um para excluir pela chave primária e outro
genérico com parâmetros? Pode, porém não há nenhuma necessidade, pois este que
criei já faz estas duas funções.
https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 13/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

C# = Copiar

public void Excluir(Func<TEntity, bool> predicate)


{
ctx.Set<TEntity>()
.Where(predicate).ToList()
.ForEach(del => ctx.Set<TEntity>().Remove(del));
}

O Dispose é usado para destruir o objeto instanciado na memória, isto é bem


comum no .NET.

public void Dispose()


{
ctx.Dispose();
}

Classe Repositório de Cliente


Nos passos anteriores criamos a interface e a classe repositório. Agora é preciso criar a
classe de repositório de cada entidade. Como temos a classe Cliente, adicione uma
nova classe chamada ClienteRepositorio na pasta Repositorio. Veja o código a seguir
com as duas referências e a herança de Repositório<TEntity>.

C# = Copiar

using Repositorio.DAL.Repositorios.Base;
using Repositorio.Entidades;

namespace Repositorio.DAL.Repositorios
{
public class ClienteRepositorio : Repositorio<Cliente>
{
}
}

Para efeito de acompanhamento, veja na figura 7 a estrutura do Solution Explorer até o


momento com os dois projetos, pastas e classes.

https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 14/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

Figura 7 – Estrutura do projeto

Compile F6 o projeto e certifique-se que está 100% com sucesso.

Projeto de Console Application


Agora que já temos toda a parte de entidade e repositório definida, podemos iniciar os
projetos que irão consumir estes outros dois. Vamos iniciar com um projeto para inserir
clientes, utilizando um recurso que citei sobre lista com ForEach. No Solution Explorer,
adicione um novo projeto do tipo Console Application chamado Repositorio.Console,
conforme a figura 8.

https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 15/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

Figura 8 – Projeto de Console

O primeiro passo a fazer é adicionar as referências. Abra o Package Console Manager,


na combobox de Default project, selecione Repositorio.Console e na linha de comando,
digite a seguinte linha para instalar o Entity Framework 6.

PM> Install-Package EntityFramework

Pronto, agora resta adicionar as referências aos outros dois projetos, conforme a figura
9.

Figura 9 – Referências dos dois projetos

Aqui vai uma dica muito importante. Este projeto de Console é o que irá consumir o
repositório, portanto, neste projeto é preciso informar a string de conexão com o banco
https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 16/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

de dados. Para isto, abra o arquivo App.config, localize a tag <entityFramework> e


antes desta, adicione as seguintes linhas:

C# = Copiar

<connectionStrings>
<add name="ConnDB" connectionString="Data Source=localhost;Initial
Catalog=BancoRepositorio;Integrated Security=True"
providerName="System.Data.SqlClient" />
</connectionStrings>

Note que a chave chama-se ConnDB, e por favor não digite diferente porque o
DbContext lá no projeto de repositório procura por este nome. Já em connectionString
você deve fornecer o caminho completo de onde pretende criar o banco de dados no
SQL Server. Sendo assim, caso tenha usuário e senha, forneça-os. Salve e feche este
arquivo.

Em seguida, abra o arquivo Program.cs, adicione os seguintes namespaces. Sendo


assim, já temos acesso ao repositório e a entidade Cliente.

C# = Copiar

using Repositorio.DAL.Repositorios;
using Repositorio.Entidades;

O único método estático Main já existe, portanto, adicione uma chamada para um
método Adicionar, assim como o código do mesmo.

C# = Copiar

namespace Repositorio.Console
{
class Program
{
static void Main(string[] args)
{
Adicionar();

private static void Adicionar()


{
using (var repClientes = new ClienteRepositorio())
{
new List<Cliente>
{
new Cliente { Nome="Microsoft", Ativo=true,
CNPJ="9394.4343/0001-55",
Endereco="1, Microsoft One",
https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 17/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

Telefone="11574739494"},
new Cliente { Nome="Google", Ativo=true,
CNPJ="1234.9494/0001-33",
Endereco="12, Santa Clara, CA",
Telefone="1185858483"},
new Cliente { Nome="Oracle", Ativo=true,
CNPJ="9876.4433/0002-44",
Endereco="54, Santa Monica",
Telefone="4884848592"}
}.ForEach(repClientes.Adicionar);

repClientes.SalvarTodos();

System.Console.WriteLine("Clientes adicionadas com


sucesso.");

System.Console.WriteLine("======= clientes cadastrados


===========");
foreach (var c in repClientes.GetAll())
{
System.Console.WriteLine("{0} - {1}", c.ClienteID,
c.Nome);
}

System.Console.ReadKey();
}
}
}
}

Vamos a explicação detalhada do método Adicionar. Como o repositório suporta o


Dispose (nós implementamos), podemos usar o using, assim quando for encontrado o
fechamento das chaves do using, o objeto já é liberado e destruído da memória. O
using faz um referência ao ClienteRepositorio, o qual foi atribuído à variável repClientes.
Em seguida é montada uma lista com Generics (List<T>) onde monto três objetos do
tipo cliente. Em seguida, como é uma lista, há o ForEach disponível que irá disparar uma
Action para um delegate dinâmico. Este delegate vai chamar o método Adicionar do
repositório repClientes. O melhor de tudo é que isto será criado em tempo de
execução.

Pergunta: Posso criar um foreach comum? Sim, você pode criar um foreach comum,
varrer toda a lista de elementos de clientes, e para cada iteração, você chama o
Adicionar do repositório. Mas, convenhamos, melhore o seu código e muito com o
Action que dispara o delegate.

Ao final, todos os clientes estarão apenas na memória, nada de banco de dados. Então,
cabe chamar o método SalvarTodos para efetivar a inclusão no banco fisicamente. Uma
vez incluídos, para ter certeza disto, criei um código para chamar o método GetAll e
listar os IDs e nomes dos clientes.
https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 18/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

Pressione F6 para compilar e certifique-se que tudo esteja 100% com sucesso. O
próximo passo é executar este projeto de Console. No entanto, na lista de projetos o de
Console não está em negrito, significando que quando você pressionar F5, o projeto em
negrito é que será executado. Então, clique com o botão direito no projeto de Console
e selecione Set as StartUp Project. Agora sim, pressione F5 e aguardo a execução onde
o banco de dados será criado na hora. Veja na figura 10 que os clientes foram
cadastrados com sucesso, pois estão listados.

Figura 10 – Clientes cadastrados

Não execute novamente senão os mesmos clientes serão adicionados. Comente a linha
da chamada do método Adicionar no Main para evitar de cadastrar tudo novamente.
Este foi o primeiro teste somente para cadastrar alguns dados.

Agora, veja um teste de como criar uma expressão Lambda e passa-la como critério
para o método de Excluir dados. No Main, crie uma chamada para o método
ExcluirVariosClientes, assim como o respectivo código.

C# = Copiar

static void Main(string[] args)


{
//Adicionar();

ExcluirVariosClientes();
}

private static void ExcluirVariosClientes()


{
using (var repClientes = new ClienteRepositorio())
{
new List<Cliente>
{
https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 19/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

new Cliente { Nome="Renato Haddad", Telefone="48575757"},


new Cliente { Nome="Renato Marcantonio", Telefone="55929292"},
new Cliente { Nome="Renato Jose", Telefone="77565644"}
}.ForEach(repClientes.Adicionar);

repClientes.SalvarTodos();
System.Console.WriteLine("Clientes Renato's adicionados");

// lista todos os clientes


foreach (var c in repClientes.GetAll())
{
System.Console.WriteLine(c.ClienteID + " - " + c.Nome);
}

// excluir vários clientes Renato


try
{
repClientes.Excluir(c => c.Nome.StartsWith("Renato"));
repClientes.SalvarTodos();
System.Console.WriteLine("clientes excluidos com sucesso");
}
catch (Exception)
{
System.Console.WriteLine("erro ao excluir um cliente");
}
System.Console.ReadKey();
}
}

Neste código basicamente adiciono três clientes que iniciam com o texto Renato, salvo
no banco e listo todos para comprovar que foram cadastrados. E, o melhor vem agora
na chamada do método repClientes.Excluir. Só para relembrar como está o método,
veja o código a seguir. A entrada é uma Func que espera uma expressão Lambda a ser
passada ao método de extensão Where do predicate que irá disparar o delegate do
ForEach para executar a exclusão dos itens que atendem ao critério.

C# = Copiar

public void Excluir(Func<TEntity, bool> predicate)


{
ctx.Set<TEntity>()
.Where(predicate).ToList()
.ForEach(del => ctx.Set<TEntity>().Remove(del));
}

E qual critério? Neste caso são todos os clientes cuja propriedade Nome inicia
(StartsWith) com “Renato”. Ou seja, serão excluídos os três clientes que inclui de teste
anteriormente. Cabe dizer que o critério é dinâmico e você pode usar todo o que for
suportado pelo C#.

https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 20/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

C# = Copiar

c => c.Nome.StartsWith("Renato")

E, para finalizar, como o Excluir foi chamado, é preciso invocar o SalvarTodos para
efetivar a exclusão dos dados no banco. Pronto, pressione F5 novamente para salvar,
compilar e executar o projeto. Caso queira abrir o banco de dados, use o Server
Explorer, conforme a figura 11.

Figura 11 – Clientes no banco

Projeto ASP.NET MVC 5


Para ilustrar o consumo do repositório em um projeto MVC 5, crie um novo projeto do
tipo Web / ASP.NET Web application, chamado Repositorio.MVC, conforme a figura 12.

Figura 12 – Novo projeto Web

https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 21/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

Clique em OK e selecione o template MVC, conforme a figura 13. Veja que não coloquei
nenhuma autenticação, pois não é preciso, iremos apenas consumir o repositório.

Figura 13 – Projeto MVC 5

Clique no botão OK e aguarde a criação do projeto completo. Logo de cara, deixe este
novo projeto como default para execução, então, no Solution Explorer clique com o
botão direito e selecione Set as Startup Project.

Agora, já instale o Entity Framework 6 via Nuget e adicione as referências aos projetos
Repositorio.Entidades e Repositorio.DAL. Pressione F6 para compilar e certifique-se que
está 100% com sucesso.

O próximo passo é referenciar a string de conexão que será usada no projeto de


Repositório.DAL. Para isto, abra o arquivo Web.Config, localize a tag </configSections >
e após esta tag, adicione o bloco a seguir. Atenção, não erre no nome da chave
ConnDB, pois esta é a chave que o DAL irá procurar para localizar o banco de dados.
Mais uma vez, nem preciso dizer que caso o seu SQL Server tenha autenticação,
adicione o UserId e a Password, assim como o nome do servidor onde o banco está.

C# = Copiar

<connectionStrings>
<add name="ConnDB" connectionString="Data Source=localhost;Initial
Catalog=BancoRepositorio;Integrated Security=True"

https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 22/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

providerName="System.Data.SqlClient" />
</connectionStrings>

Controller de Clientes
Um projeto MVC 5 é tão fácil de se criar todas as Views de CRUD, que há templates
(scaffolds) prontos. E, a primeira coisa a fazer é criar o Controller de Clientes. Compile o
projeto novamente F6. Na pasta Controllers, clique com o botão direito, selecione Add /
Controller. Será aberta a janela de Scaffold (templates) conforme a figura 14, então
selecione MVC 5 Controller with views, using Entity Framework.

Figura 14 – Adicionar um controller usando o Entity Framework

Clique no botão Add e preencha os dados conforme a figura 15, sendo: Controller
(Controller name) = ClientesController; Model class = Cliente; Data context class =
BancoContexto.

https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 23/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

Figura 15 – Informações para o Controller

Clique no botão Add e aguarde o Visual Studio criar ClientesController e todas as Views
(UI) para fazer o CRUD de dados.

Ajustes no Controller
Na pasta Controller tem o arquivo ClientesController.cs criado automaticamente usando
o scaffold do MVC 5. No entanto, como temos o repositório é preciso fazer alguns
ajustes. Sendo assim, no código a seguir, o que for default do MVC 5 eu coloquei como
comentário, e o código que você deverá digitar está em seguida dos comentários.
Basicamente é preciso retirar todas as referências do contexto e apontar para o
ClienteRepositorio.

C# = Copiar

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using Repositorio.Entidades;
using Repositorio.DAL.Contexto;
using Repositorio.DAL.Repositorios;
https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 24/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

namespace Repositorio.MVC.Controllers
{
public class ClientesController : Controller
{
// Troca o contexto
//private BancoContexto db = new BancoContexto();
private readonly ClienteRepositorio repCli = new
ClienteRepositorio();

// GET: /Clientes/
public ActionResult Index()
{
//return View(db.Cliente.ToList());
return View(repCli.GetAll().ToList());
}

// GET: /Clientes/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
//Cliente cliente = db.Cliente.Find(id);
Cliente cliente = repCli.Find(id);

if (cliente == null)
{
return HttpNotFound();
}
return View(cliente);
}

// GET: /Clientes/Create
public ActionResult Create()
{
return View();
}

// POST: /Clientes/Create
// To protect from overposting attacks, please enable the specific
properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult
Create([Bind(Include="ClienteID,Nome,CNPJ,Endereco,Telefone,Ativo")] Cliente
cliente)
{
if (ModelState.IsValid)
{
//db.Cliente.Add(cliente);
repCli.Adicionar(cliente);

https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 25/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

//db.SaveChanges();
repCli.SalvarTodos();
return RedirectToAction("Index");
}

return View(cliente);
}

// GET: /Clientes/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
//Cliente cliente = db.Cliente.Find(id);
Cliente cliente = repCli.Find(id);
if (cliente == null)
{
return HttpNotFound();
}
return View(cliente);
}

// POST: /Clientes/Edit/5
// To protect from overposting attacks, please enable the specific
properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult
Edit([Bind(Include="ClienteID,Nome,CNPJ,Endereco,Telefone,Ativo")] Cliente
cliente)
{
if (ModelState.IsValid)
{
//db.Entry(cliente).State = EntityState.Modified;
repCli.Atualizar(cliente);

//db.SaveChanges();
repCli.SalvarTodos();
return RedirectToAction("Index");
}
return View(cliente);
}

// GET: /Clientes/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
//Cliente cliente = db.Cliente.Find(id);
Cliente cliente = repCli.Find(id);
https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 26/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

if (cliente == null)
{
return HttpNotFound();
}
return View(cliente);
}

// POST: /Clientes/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
//Cliente cliente = db.Cliente.Find(id);
Cliente cliente = repCli.Find(id);

//db.Cliente.Remove(cliente);
repCli.Excluir(c => c == cliente);

//db.SaveChanges();
repCli.SalvarTodos();
return RedirectToAction("Index");
}

protected override void Dispose(bool disposing)


{
//if (disposing)
//{
// db.Dispose();
//}
repCli.Dispose();
base.Dispose(disposing);
}
}
}

Pressione F6 para compilar o projeto, e caso tenha algum erro, corrija-o.

Views (UI interface de usuário)


Uma vez criado o Controller são criadas todas as Views do Cliente automaticamente,
como você pode ver na pasta Views/Clientes na figura 16.

https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 27/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

Figura 16 – Views do Cliente

Por se tratar de um projeto MVC 5, vamos fazer um ajuste para aparecer a opção
Cliente no menu da View principal. Localize o arquivo _Layout.cshtml na pasta
Views/Shared. Na lista de opções do menu adicione a chamada para Clientes.

C# = Copiar

<div class="navbar-collapse collapse">


<ul class="nav navbar-nav">
<li>@Html.ActionLink("Home", "Index", "Home")</li>
<li>@Html.ActionLink("Clientes", "Index", "Clientes")</li>
<li>@Html.ActionLink("About", "About", "Home")</li>
<li>@Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>
</div>

Pronto, o projeto já está finalizado utilizando todos os recursos de repositório de


dados, em camadas e independentes para você testar cada camada individualmente.
Para manutenção de qualquer código é muito mais fácil, produtivo e o melhor de tudo
é que para um cenário de times médios e grandes, isto se aplica perfeitamente.
Pressione F5 para salvar, compilar e executar a aplicação MVC 5. Conforme a figura 17,
clique no menu Clientes para visualizar todos os clientes cadastrados.

https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 28/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

Figura 17 – Clientes cadastrados

Caso queira cadastrar um novo cliente, clique em Create New, ou então, em qualquer
outra opção disponível para alterar, detalhes ou excluir. Veja a tela de cadastro na figura
18.

https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 29/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

Figura 18 – Novo cliente

Eu sugiro você utilizar o breakpoint no Controller para identificar todo o caminho das
camadas percorridas pelo código, afinal o Debug é fantástico pra isto.

Neste artigo criei apenas um projeto de Console e MVC 5, mas fique à vontade para
criar qualquer outro tipo de projeto. E, caso necessite aplicar o repositório como serviço
que retorne um JSON ou XML, crie um projeto de Web Api que referencia o repositório
e pronto.

Conclusão
O uso de repositórios de dados tem sido usado em projetos de várias tecnologias, e em
.NET demonstrei uma maneira que compartilho com todos os leitores, alguns códigos
https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 30/31
05/08/2019 Repositório de Dados no Entity Framework 6 | Microsoft Docs

para que você possa implementar nos vossos projetos. Sei que é preciso estudar um
pouco mais sobre códigos dinâmicos, actions, predicates, expressões lambda e o entity
framework 6, mas isto é o que nos move para os desafios de criar projetos produtivos.
Particularmente, sempre irei incentivar o estudo de novidades porque tenho certeza
que há sempre o que se aprender e melhorar. Caso você tenha algum comentário ou
queira compartilhar códigos com os desenvolvedores, faça isto com prazer e saiba que
quanto mais você compartilhar, mais você receberá em troca, afinal é um processo
natural de evolução.

Agradeço a oportunidade de poder compartilhar o conhecimento com todos. Qualquer


dúvida e preparação de times de desenvolvimento, por favor me contate.

Sobre o Autor
Renato Haddad (rehaddad@msn.com – www.renatohaddad.com ) é MVP, MCT, MCPD e
MCTS, palestrante em eventos da Microsoft em diversos países, ministra treinamentos
focados em produtividade com o VS.NET 2012/2013, ASP.NET 4/5, ASP.NET MVC, Entity
Framework, Reporting Services, Windows Phone e Windows 8. Visite o blog
http://weblogs.asp.net/renatohaddad.

| Home | Artigos Técnicos | Comunidade

https://docs.microsoft.com/pt-br/previous-versions/technical-articles/dn630213(v=msdn.10) 31/31

Você também pode gostar