Criando um repositório genérico para Entity Framework

Standard

Irei demonstrar aqui uma forma bem simples e rápida para implementarmos um repositório genérico com Entity Framework. A ideia de implementação será a mesma utilizada com Linq to SQL, ou seja, nosso repositório será responsável por realizar apenas quatro operações: Selecionar os dados, salvar, apagar e atualizar.

Vamos primeiramente criar uma interface para o repositório:

public interface IRepositorio
{
	void Atualiza();

	void Apaga<TEntidade>(TEntidade entidade) where TEntidade : class;

	void Salva<TEntidade>(TEntidade entidade) where TEntidade : class;

	IQueryable<TEntidade> Seleciona<TEntidade>() where TEntidade : class;
}


Agora vamos ao principal, a implementação de fato dos métodos:

public class Repositorio : IRepositorio
{
	private readonly DB _db;

	public Repositorio(DB db)
	{
		_db = db;
	}

	public void Atualiza()
	{
		_db.SaveChanges();
	}

	public void Apaga<TEntidade>(TEntidade entidade) where TEntidade : class
	{
		_db.DeleteObject(entidade);
		Atualiza();
	}

	public void Salva<TEntidade>(TEntidade entidade) where TEntidade : class
	{
		_db.AddObject(typeof(TEntidade).Name, entidade);
		Atualiza();
	}

	public IQueryable<TEntidade> Seleciona<TEntidade>() where TEntidade : class
	{
		return _db.CreateObjectSet<TEntidade>();
	}
}

Legal e muito simples não? porém, sei que algumas dúvidas devem estar presentes, vejamos:

 

Perguntas/Respostas

1-) Em que momento é realizado o new no objeto DB ? Exemplo: _db = new DB();
Resposta: Para o exemplo utilizei IoC – Injeção de Dependência, veja aqui um post sobre o assunto.

2-) Não estaria faltando um método para permitir a seleção de apenas um registro no DB?
Resposta: Acredito que não. Isso pelo fato de que nosso método chamado ‘Seleciona’ retorna um IQueryable, desta forma, auxiliado pelo Deferred Loading nossa query ainda não foi executada de fato no DB até que haja uma iteração concreta na mesma. Desta forma podemos realizar uma seleção única posteriormente.

3-) Mas seria errado criar o método para seleção única no repositório ?
Resposta: Não. Seria uma implementação bem simples por sinal, veja:

public TEntidade Seleciona<TEntidade>(string whereLinq) where TEntidade : class
{
	return _db.CreateObjectSet<TEntidade>().Where(whereLinq).FirstOrDefault();
}

Antes da próxima pergunta já adianto, sim, estou utilizando Dynamic Linq para efetuar nosso where, mas nada o impede de utilizar outros recursos como Predicated Builder, etc! 🙂

4-) E como seria realizado um Update de algum regitro no DB?
Resposta: Irei demonstrar um Update de uma forma bem rápida e simples, porém, a ideia é a mesma para objetos mais complexos. Veja:

public class Service : IService
{
	private readonly Repositorio _repositorio;

	public Service(Repositorio repositorio)
	{
		_repositorio = repositorio;
	}

	public void TesteAtualizaRegistro()
	{
		//Seleciona o Produto que possua código igual a 1
		var p = _repositorio.Seleciona<Produto>("cod = 1");
		
		//Seta os novos valores para as propriedades nome e valor
		p.nome = "Nome Atualizado";
		p.valor = 130;
		
		//Chama método Atualiza no repositório, aqui é efetuado o SaveChanges()
		_repositorio.Atualiza();
	}
}

Deu para captar? atente-se que para a atualização funcionar, o método Atualiza() deve ser chamado após os novos valores serem setados. Simples assim!

 

Considerações Finais

O uso de um repositório genérico ajuda e muito a padronização do nosso código, além de facilitar as principais operações e viabiliza-las em um único lugar. Considere aprender e aplicar outros conceitos e tecnologias, como por exemplo: IoC, UoW, Dynamic Linq, AutoMapper, Predicated Builder, etc. Dúvidas, sugestões, críticas serão muito bem vindas!

Abs e até a próxima.

 

Leave a Reply

Your email address will not be published. Required fields are marked *