Nesse artigo eu mostro como usar o Repository Pattern para acessar banco de dados. Eu demostro esse conceito usando o banco de dados SQL com o componente de acesso a dados Dapper (Stackoverflow) e outro usando banco de dados MongoDB com o driver oficial do .NET.
MongoDB é um dos bancos de dados gratuitos NÃO-RELACIONAL mais populares que existem. Isso quer dizer, comparando com o SQL Server, ele não possui tabelas que se relacionam entre si através de chaves primárias ou secundárias, e sim MongoDB trabalha com documentos (normalmente em JSON) que podem armazenar um conjunto de dados inteiro.
Conheça mais a fundo Repository Pattern e outros Design Patterns no meu eBook totalmente gratuito da série Programação no Mundo Real: Design Patterns vol.1.
Uma das principais regras do Repository Pattern é que a classe de negócios não precisa saber onde os dados estão armazenados ou simplemente não precisa saber qual é o banco de dados que está sendo utilizado.
Vamos começar essa parada!
Para esse código, você poderá usar o Visual Studio 2017 se preferir, mas dê uma olhada no artigo que escrevi UNBOXING VS2017: Primeiras Impressões no Mundo Real decida se realmente precisa do 2017.
Repository Pattern
O que é ou para que serve?
É um elo de ligação entre a camada de negócios e a camada de acesso a dados sem que a camada de negócios saiba qual é a base de dados que está sendo acessada.
Onde uso?
No acesso a base de dados.
Principal regra ou cenário:
Criar uma interface e uma classe que implementa essa interface. Nessa classe herde de uma outra classe básica que fará o acesso a base de dados correspondente.
O objetivo principal do exemplo é criar um método para buscar “taxas” (para calcular alguma coisa) em determinado repositório de dados.
Vamos definir a interface ITaxaRepository para o repositório:
public interface ITaxaRepository : IDisposable { Task<IEnumerable<Models.Taxa>> ListarTaxa(int codigo); }
Segundo passo é criar a classe do repositório para o MongoDB:
public class MongoDBTaxaRepository : MongoDBRepository, ITaxaRepository { public async Task<IEnumerable<Taxa>> ListarTaxa(int codigo) { // comente esse bloco quando instalar o MONGODB, criar a tabela e carregar de dados antes. return await Task.Run(() => { var taxas = new List<Taxa>(); taxas.Add(new Taxa { Codigo = 1, Valor = 10, Fator = 2 }); return taxas; }); //código da implementação de mongodb return await Database.GetCollection<Taxa>("Taxas") .Find(x => x.Codigo == codigo) .ToListAsync(); } }
A classe de MongoDBTaxaRepository busca as taxas no MongoDB e serializa o documento em uma lista de Taxa. Uma coisa interessante a perceber é que essa classe herda de outra classe básica MongoDBRepository.
MongoDBRepository server para se conectar ao MongoDB e pode ser facilmente reutilizada:
public class MongoDBRepository : IDisposable { public MongoDBRepository() : this("localhost") { } public MongoDBRepository(string databaseName) { DatabaseName = databaseName; _client = new MongoClient(); _database = _client.GetDatabase(DatabaseName); } public void Dispose() { _client = null; _database = null; } public string DatabaseName { get; set; } private IMongoClient _client; private IMongoDatabase _database; public IMongoDatabase Database { get { return _database; } } }
O próximo passo e criar a classe de acesso ao banco de dados SQL usando Dapper, então vamos fazer isso já!
DapperTaxaRepository com Dapper acessando SQL Server:
public class DapperTaxaRepository : SqlServerRepository, ITaxaRepository { public async Task<IEnumerable<Taxa>> ListarTaxa(int codigo) { var command = @"SELECT Valor, Fator, Codigo FROM Taxas WHERE Codigo = @codigo"; return await Database.QueryAsync<Taxa>(command, new { codigo = codigo }); } }
O uso do Dapper é muito simples pois possui diversos Extensions Methods úteis para realizar as consultas e operações no banco de dados SQL.
O comando básico para consultas com Dapper é enviar uma string contendo o comando SQL para o método QueryAsync explicitando a serialização/conversão dos dados para a model Taxa. No último parâmetro deste método, passe um objeto anônimo para ser usado na cláusula WHERE. Fácil hein! Retornará uma lista de taxas.
Ambas as classes MongoDBTaxaRepository e DapperTaxaRepository implementam a interface ITaxaRepository.
DapperTaxaRepository também herda de uma classe básica SqlServerRepository, que serve para se conectar ao banco de dados SQL e também pode facilmente ser reutilizada:
public class SqlServerRepository : IDisposable { public SqlServerRepository() : this("sqlserver") { } public SqlServerRepository(string connectionStringId) { _connectionStringId = connectionStringId; } public virtual string ConnnectionStringId { get { return _connectionStringId; } } protected SqlConnection Database { get { if (_connection == null) { if (string.IsNullOrEmpty(_connectionString)) { _connectionString = ConfigurationManager.ConnectionStrings[ConnnectionStringId].ConnectionString; } _connection = new SqlConnection(_connectionString); } return _connection; } } public SqlServerRepository UseConnectionStringId(string connectionStringId) { _connectionStringId = connectionStringId; return this; } public SqlServerRepository UseConnectionString(string connectionString) { _connectionString = connectionString; return this; } public virtual void Dispose() { if (_connection != null) { _connection.Close(); _connection.Dispose(); _connection = null; } } private SqlConnection _connection = null; private string _connectionStringId; private string _connectionString; }
Exemplos de uso:
// Exemplos de chamadas paralelas usando diferentes repositórios // TaxaService se vira para achar o repositório var calculoA = TaxaService.CalcularTaxa(1); // TaxaService recebe o repositório (instanciado via Dependency Injection) var calculoB = TaxaService.CalcularTaxa(1, _repository); // TaxaService recebe o repositório especifico do MongoDB var calculoC = TaxaService.CalcularTaxa(1, new MongoDBTaxaRepository()); await Task.WhenAll(calculoA, calculoB, calculoC);
Eu costumo usar Dependency Injection na definição dos serviços, onde configuro o apontamento uma interface para uma determinada classe sem explicitá-la (primeiro exemplo).
Conheça mais a fundo Dependency Injection no meu eBook totalmente gratuito da série Programação no Mundo Real: Design Patterns vol.1.
Bom é isso. Espero que tenha ajudado.
Ajude a aprimorar o conteúdo deste site sugerindo um artigo ou tema.
Repository Pattern com Dapper SQL e MongoDB
Repository SQL Dapper MongoDB: Perguntas, sugestões ou críticas são bem vindas. Boa sorte!
Esse artigo dedico as 30 Pessoas que Influenciaram Minha Carreira Profissional.
Faça download completo do código fonte no github. |