Utilizando o MongoDB em aplicações .NET

NetCoders
netcoders
Published in
9 min readFeb 13, 2016
mongo-00

É inegável a importância dos bancos de dados relacionais dentro do mundo corporativo. O surgimento desta tecnologia revolucionou o tratamento de informações nos mais variados ramos de atuação, conferindo agilidade e flexibilidade às organizações em suas operações cotidianas. Este uso em larga escala de bases relacionais deve certamente continuar, tendo como pilares a linguagem SQL e a praticidade desta última na manipulação de dados.

Por mais que a tecnologia relacional atenda a um amplo escopo de necessidades, em alguns cenários bem específicos esta abordagem pode não ser a solução mais adequada:

  • Questões como uma alta disponibilidade e a capacidade de um sistema de banco de dados se adaptar a níveis de uso crescentes (escalabilidade) costumam exigir pesados investimentos em infraestrutura. Nem sempre existirão recursos disponíveis (financeiros ou não) para atender a tais demandas imediatamente;
  • A estrutura rígida de linhas e colunas das tabelas relacionais também será um fator limitante em determinados contextos. A adaptação de uma base convencional para agrupamentos de dados mais complexos pode se revelar uma tarefa bastante árdua, sobretudo se o conteúdo em questão apresentar um formato variável.

Uma opção às dificuldades aqui levantadas seria o uso de uma solução NoSQL (sigla interpretada por alguns como “Not only SQL”). Tecnologias em conformidade com este paradigma costumam adotar uma estrutura diferente daquela tipicamente relacional, de forma a oferecer assim uma resposta a requisitos como alta disponibilidade, escalabilidade e a necessidade de uma estrutura para armazenamento mais flexível. Diversos são os bancos de dados NoSQL disponíveis no mercado, com o MongoDB correspondendo a uma das alternativas mais populares entre desenvolvedores de software.

O objetivo deste artigo é trazer uma visão geral do MongoDB, bem como de que maneira o mesmo pode ser utilizado na implementação de projetos baseados no .NET Framework.

Um pouco mais sobre o MongoDB

O nome MongoDB tem sua origem na palavra inglesa “humongous”, termo este geralmente empregado para expressar algo considerado gigantesco. Trata-se de uma solução gratuita e open source mantida por uma empresa chamada MongoDB Inc. (anteriormente conhecida como 10gen), encontrando-se atualmente (Fevereiro/2016) na versão 3.2.

Do ponto de vista estrutural o MongoDB conta com as seguintes características:

  • Ao invés de registros organizados em tabelas relacionais formadas por colunas com um tipo pré-definido, um banco do MongoDB é composto por coleções; cada coleção, por sua vez, é constituída por uma série de documentos (Imagem 1). Por esse motivo este produto é classificado como um banco de dados NoSQL baseado em documento;
  • Os documentos no MongoDB são formados por campos (o equivalente a colunas no modelo relacional), empregando um formato conhecido como BSON para o armazenamento de informações. Já o padrão BSON (abreviação de binary JSON) representa uma variação da especificação JSON com suporte à manipulação de dados binários, além de tipos convencionais como strings ou valores numéricos;
  • A utilização de uma estrutura baseada em JSON torna o MongoDB um banco schemaless, ou seja, sem um esquema rígido. Isto permite a utilização de um formato flexível para os diferentes documentos que venham a compor uma coleção, diferentemente das colunas que seguem um padrão pré-definido para todos os registros em uma tabela relacional;
  • Todo documento criado no MongoDB conta com um campo chamado “_id”, o qual nada mais é do que um identificador único e gerado automaticamente no momento da inclusão deste elemento;
  • Além dos aspectos mencionados, o MongoDB possui ainda o suporte a informações geoespaciais (incluindo latitude e longitude) e permite a criação de índices para a otimização de consultas.
mongo-01

Imagem 1. Estrutura geral de um banco de dados no MongoDB

OBSERVAÇÃO: maiores detalhes sobre a arquitetura empregada pelo MongoDB podem ser encontrados na seção “Referências”.

Instalando o MongoDB no Windows

O download da versão do MongoDB para Windows pode ser efetuado através do seguinte link:

ATENÇÃO: Os procedimentos descritos nesta seção foram realizados em uma máquina com o Windows 10 Professional instalado (estas ações são válidas, a princípio, em outras versões do Windows suportadas pelo MongoDB).

Por motivos de simplificação, a instalação do MongoDB foi efetuada no diretório C:\MongoDB\. Também será necessário criar o diretório C:\data\db\, o qual corresponde ao espaço utilizado pelo MongoDB para a geração de arquivos com dados e logs.

Para ativar o uso do MongoDB acionar o executável mongod.exe, instalado em C:\MongoDB\bin\. Com isto o servidor deste banco NoSQL estará no ar (Imagem 2). Vale destacar que a execução do arquivo mongod.exe pode acontecer tanto via prompt de comando, quanto por meio do agendamento de uma tarefa no Windows.

mongo-02

Imagem 2. O utilitário mongod.exe em execução

A execução de ações em bancos de dados do MongoDB pode ser feita por meio do utilitário de linha de comando mongo.exe (também criado em C:\MongoDB\bin\). Na Imagem 3 é possível observar esta aplicação em ação.

mongo-03

Imagem 3. O utilitário mongo.exe em execução

MongoDB e o .NET Framework

O package para acesso ao MongoDB em soluções .NET (MongoDB.Driver) pode ser instalado via NuGet no Visual Studio, como indicado na Imagem 4. Para os exemplos descritos nesta seção foi utilizada a versão 2.2.3 deste driver.

mongo-04

Imagem 4. Adicionando o MongoDB.Driver a uma aplicação .NET

Ao se realizar este procedimento serão adicionadas ao projeto as referências destacadas na Imagem 5:

mongo-05

Imagem 5. Bibliotecas do MongoDB adicionadas a uma aplicação .NET

Para os exemplos envolvendo a integração MongoDB-C# será utilizada a classe Cidade, cuja definição encontra-se na Listagem 1:

  • A propriedade _id corresponde ao identificador único de um documento, tendo sido declarada como do tipo ObjectId (namespace MongoDB.Bson);
  • Também foram definidos campos representando o nome e o estado de uma cidade.

[sourcecode language=”csharp”]
using MongoDB.Bson;

namespace TesteMongoDB
{
class Cidade
{
public ObjectId _id { get; set; }
public string Nome { get; set; }
public string Pais { get; set; }
}
}
[/sourcecode]

Listagem 1: Classe Cidade

A Listagem 2 demonstra a inclusão de uma cidade em um banco de dados chamado ExemploCSharp:

  • Uma primeira variável foi declarada de forma a armazenar a conexão de acesso local ao servidor do MongoDB (por default, o mesmo é instalado na porta 27017);
  • Será gerada então uma instância da classe MongoClient (namespace MongoDB.Driver), que servirá de base para o acesso aos bancos NoSQL existentes em um servidor;
  • Uma referência a um banco de dados será obtida invocando o método GetDabase do objeto MongoClient; esta operação recebe como parâmetro o nome de uma base, trazendo como resultado uma instância do tipo IMongoDatabase (namespace namespace MongoDB.Driver);
  • Com a referência de IMongoDatabase será acionado o método GetCollection, com este último recebendo como parâmetros a classe que representa um documento e o nome da coleção a ser manipulada. O retorno desta ação será uma referência baseada na interface genérica IMongoCollection (namespace MongoDB.Driver);

Uma instância do tipo Cidade é então criada, com o preenchimento das propriedades que serão persistidas no banco de dados. Por fim, o método InsertOne será executado, procedendo com a inclusão dos dados na base; neste momento constará na propriedade _id o valor único gerado pelo MongoDB para esse novo documento.

[code language=”csharp”]

string connectionString = “mongodb://localhost:27017”;

MongoClient client = new MongoClient(connectionString);
IMongoDatabase db = client.GetDatabase(“ExemploCSharp”);

var cidades = db.GetCollection<Cidade>(“cidades”);

Cidade cidade = new Cidade();
cidade.Nome = “Roma”;
cidade.Pais = “Italia”;

cidades.InsertOne(cidade);

ObjectId _idInclusao = cidade._id;


[/code]

Listagem 2: Adicionando um novo documento

É importante ressaltar que, na eventualidade de um banco e/ou coleção ainda não existir fisicamente, o procedimento descrito nesta segunda listagem fará com que tais elementos sejam automaticamente criados. Na Imagem 6 está o resultado de uma consulta à coleção “cidades” após a execução deste último trecho de código:

mongo-06

Imagem 6. Coleção após da inclusão de uma primeira cidade

O próximo passo agora será alterar a classe cidade, adicionando à mesma um campo que referencie o estado/província (Listagem 3):

[code language=”csharp” highlight=”9"]
using MongoDB.Bson;

namespace TesteMongoDB
{
class Cidade
{
public ObjectId _id { get; set; }
public string Nome { get; set; }
public string Estado { get; set; }
public string Pais { get; set; }
}
}
[/code]

Listagem 3: Classe Cidade após inclusão do campo Estado

A Listagem 4 apresenta um trecho de código que efetuará um teste já contemplando o uso da propriedade Estado:

[code language=”csharp” highlight=”12"]

string connectionString = “mongodb://localhost:27017”;

MongoClient client = new MongoClient(connectionString);
IMongoDatabase db = client.GetDatabase(“ExemploCSharp”);

var cidades = db.GetCollection<Cidade>(“cidades”);

Cidade cidade = new Cidade();
cidade.Nome = “Sao Paulo”;
cidade.Estado = “Sao Paulo”;
cidade.Pais = “Brasil”;

cidades.InsertOne(cidade);

ObjectId _idInclusao = cidade._id;


[/code]

Listagem 4: Adicionando um segundo documento

Para localização de documentos o driver do MongoDB disponibiliza o método Find, que deverá ser invocado a partir de uma coleção (Listagem 5). A expressão lambda informada como parâmetro neste exemplo retornará sempre true, de forma a retornar todos os elementos existentes:

[code language=”csharp” highlight=”8,9"]

string connectionString = “mongodb://localhost:27017”;

MongoClient client = new MongoClient(connectionString);
IMongoDatabase db = client.GetDatabase(“ExemploCSharp”);

List<Cidade> cidades = db.GetCollection<Cidade>(“cidades”)
.Find(_ => true).ToList();


[/code]

Listagem 5: Retornando todos os elementos de uma coleção

Expressões lambda mais específicas podem ser utilizadas, de forma a permitir a localização de itens específicos (Listagem 6):

[code language=”csharp” highlight=”8,9"]

string connectionString = “mongodb://localhost:27017”;

MongoClient client = new MongoClient(connectionString);
IMongoDatabase db = client.GetDatabase(“ExemploCSharp”);

Cidade cidade = db.GetCollection<Cidade>(“cidades”)
.Find(c => c.Nome == “Roma”).ToList().First();


[/code]

Listagem 6: Localizando um documento específico

Na Listagem 7 é possível observar um exemplo envolvendo a atualização de um documento:

  • Inicialmente será localizado o elemento a ser modificado, empregando-se para isto o método Find em conjunto com uma expressão lambda;
  • Modificações são então realizadas na referência obtida;
  • Na sequência o método ReplaceOne é invocado. O primeiro parâmetro informado representa uma expressão lambda baseada na propriedade _id, ao passo que o segundo valor é a própria instância do tipo Cidade com os dados a serem atualizados.

[code language=”csharp” highlight=”10,11,12,13,14"]

string connectionString = “mongodb://localhost:27017”;

MongoClient client = new MongoClient(connectionString);
IMongoDatabase db = client.GetDatabase(“ExemploCSharp”);

var cidades = db.GetCollection<Cidade>(“cidades”);

Cidade cidade = cidades
.Find(c => c.Nome == “Sao Paulo”).ToList().First();
cidade.Estado = “SP”;

cidades.ReplaceOne(c => c._id == cidade._id, cidade);


[/code]

Listagem 7: Atualizando um documento

As modificações efetuadas até este ponto podem ser visualizadas na Imagem 7.

mongo-07

Imagem 7. Coleção após inclusões e alterações

Finalmente a Listagem 8 traz um caso de exclusão de um documento:

  • Trata-se de um processo bastante similar àquele descrito para alterações, envolvendo novamente o uso do método Find;
  • O método DeleteOne é acionado, recebendo como parâmetro uma expressão lambda cujo filtro fará uso da propriedade _id e procedendo com a remoção do elemento em questão.

[code language=”csharp” highlight=”8,9,10"]

string connectionString = “mongodb://localhost:27017”;

MongoClient client = new MongoClient(connectionString);
IMongoDatabase db = client.GetDatabase(“ExemploCSharp”);

var cidades = db.GetCollection<Cidade>(“cidades”);

cidades.DeleteOne(c => c.Nome == “Roma”);


[/code]

Listagem 8: Excluindo um documento

Na Imagem 8 está o resultado após a exclusão realizada neste último passo.

mongo-08

Imagem 8. Coleção após a exclusão

Conclusão

Assim como outras soluções NoSQL, o MongoDB se destaca pela sua flexibilidade, compatibilidade com diversas plataformas de desenvolvimento e poder de processamento. Contudo, será necessário sempre se proceder com uma análise bem criteriosa quanto à adoção deste banco de dados. É importante ter em mente que o modelo relacional não perderá sua importância e, em muitos casos, ainda continuará a ser a alternativa mais adequada na implementação de novos projetos.

Espero que este post tenha sido útil.

Até uma próxima oportunidade!

Referências

Exemplo de utilização do MongoDB em uma aplicação .NET
https://gallery.technet.microsoft.com/Exemplo-de-utilizao-do-a3cb1f6c

Configuração do ambiente para MongoDB no Windows
https://pablojuancruz.wordpress.com/2014/09/03/configurando-ambiente-mongodb-no-windows/

FAQ: MongoDB Fundamentals
https://docs.mongodb.org/manual/faq/fundamentals/

The MongoDB Manual
https://docs.mongodb.org/manual/

--

--