.NET

21 dez, 2016

Como usar .NET Core em produção hoje com aplicações Web: MongoDB

Publicidade

Até recentemente, quando alguém me perguntava se devia começar a usar o ASP.NET Core e me pedia um roadmap do uso de ASP.NET Core, a resposta era “SIM! Comece hoje!”. Mas dado o fato de que o Entity Framework Core ainda não tem features suficientes para suportar uma aplicação de negócios que não seja muito simples, eu recomendava que a pessoa começasse a usar o ASP.NET Core hoje, mas sem .NET Core, com .NET Full. Veja por que:

O Entity Framework Core não está pronto, mas se for sua preferência usá-lo no futuro, comece com o EF 6.1.3, que é a versão mais atual. Não rode no Linux ou no Mono, porque não há suporte da Microsoft. Se precisar de contêineres Docker, use um contêiner Windows, não Linux. Quando o Entity Framework evoluir, o que não deve acontecer no primeiro semestre do ano que vem de forma satisfatória ainda, migre para ele. Haverá quebra de compatibilidade, tanto no ASP.NET Core, quanto no EF; mas elas serão gerenciáveis.

O NHibernate não suporta o .NET Core, mas, se quiser, você pode fazer uma aposta de que ele irá migrar e suportar o .NET Standard em algum momento. Nesse caso, use o NHibernate atual, versão 4.0.4.4000, e siga as mesmas recomendações a respeito do uso do Mono e de contêineres que dei acima. O Elemar Jr. nos disse, durante o TDC São Paulo, que tinha ficado sabendo pelo Ayende (um dos contribuidores do NH), de que haveria uma migração para o .NET Standard em algum momento. Eu imagino que eles devem esperar o .NET Standard 2.0, que vai trazer uma série de APIs essenciais para essa migração, ou seja, temos que esperar até o meio do ano que vem (no mínimo).

De qualquer forma, a posição deles segue em aberto – veja o issue 3807, que toca no assunto no Jira do NHibernate e leia os comentários. Note que ainda falta muita definição se isso vai de fato acontecer. É uma aposta maior do que a do EF. Um fato interessante é que, se o NHibernate não evoluir pro Core, aposto que vai morrer, vai virar legado, ficar no passado. Além disso, eles precisam também implementar suporte para async e await, algo que parece estar previsto (leia os comentários do issue 3807; eles tocam no assunto).

Note que não há muita saída. Mas há, se você se libertar do que há de mais comum no ecossistema .NET. Vamos olhar em volta?

Rodando .NET Core em uma app complexa usando MongoDB

Nem só de SQL vivem os projetos web. Notei que o Nuget do MongoDB foi atualizado recentemente, e qual não foi minha surpresa, ao notar que agora ele suporta .NET Standard. Veja você mesmo o pacote MongoDB.Driver no Nuget. A versão 2.3.0 suporta o .NET Standard versão 1.5 desde o seu RC1, lançado em 29 de agosto, e já está em RTM desde 23 de setembro. Ou seja, roda com .NET Core sem qualquer problema. A versão 2.x do componente do Mongo suporta uma série de funcionalidades novas, e é totalmente funcional, incluindo, inclusive, async e await, um mapeador Object Model, documentos embedded ou referências, índices, entre muitas outras funcionalidades poderosas. Ou seja, você usa MongoDB em toda sua capacidade.

Fui verificar se tudo funcionava e não houve nenhum problema. Tudo rodou perfeitamente. Subi também um contêiner Docker e também funcionou muito bem. Veja abaixo alguns highlights. Testei a versão beta 1 do 2.4.0.

Criei um método AddMongo no projeto, que lê as configurações. O meu método ConfigureServices no Startup.cs ficou limpo, vejam só:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddMongo(Configuration.GetSection("Mongo"));
}

O meu appsettings.json ganhou essa seção Mongo especificada:

{
    "Mongo": {
        "ConnectionString": "mongodb://localhost:27017"
    }
}

O método AddMongo não poderia ser mais simples:

public static void AddMongo(this IServiceCollection services, IConfigurationSection configuration)
{
    services.AddSingleton(new MongoClient(configuration.GetSection("ConnectionString").Value));
}

Isso já me permite rodar a aplicação e injetar em qualquer lugar um MongoClient. Fiz isso de maneira bem simples, direto no controller:

public PeopleController(MongoClient client)
{
    var database = client.GetDatabase("mongodbdotnetcore");
    people = database.GetCollection<Person>(nameof(people));
}

Para exibir um item que seria editado, é só usar a collection obtida acima, note o suporte a async e await:

public async Task<ActionResult> Edit(string id)
{
    var personCursor = await people.FindAsync(Builders<Person>.Filter.Eq(p => p.Id, ObjectId.Parse(id)));
    var person = await personCursor.FirstOrDefaultAsync();
    return View(person);
}

E para salvar o item, é também bastante simples:

public async Task<ActionResult> Edit(string id, Person person)
{
    if (!ModelState.IsValid)
        return View();
    person.Id = ObjectId.Parse(id);
    await people.ReplaceOneAsync(Builders<Person>.Filter.Eq(p => p.Id, person.Id), person);
    return RedirectToAction(nameof(Index));
}

Tudo funcionou perfeitamente. Não vou mostrar o código das views, mas você pode baixar o código depois e olhar.

Rodando com Docker

Além disso, criei um Dockerfile para testar em um contêiner. Veja como ele ficou simples:

FROM microsoft/dotnet:1.0.0-preview2-sdk
WORKDIR /app
ENV ASPNETCORE_URLS http://*:5000
EXPOSE 5000
COPY . /app
RUN dotnet restore
CMD dotnet run

Eu usei a imagem oficial do .NET Core para Linux (baseada em Debian), adicionei os arquivos do projeto, restaurei e rodei.

E criei também um arquivo para Docker Compose (docker-compose.yml) para facilitar a execução:

version: '2'
services:
  web:
    image: giggio/mongodbdotnetcore
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "5000:5000"
    links:
      - "db"
    environment:
      - Mongo:ConnectionString=mongodb://db:27017
  db:
    image: mongo
    ports:
      - "27017"

Para testar, basta rodar:

docker compose up

Note que no Docker Compose já criamos um banco MongoDB e ligamos ele ao contêiner do projeto web, enquanto setamos a variável que configura a string de conexão para usar o banco ligado.

Veja o resultado final:

image_thumb-17

Aqui, a aplicação rodando na tela de listagem:

image_thumb-18

Tela de criação de uma nova entidade:

image_thumb-19

Nesse caso, a aplicação estava rodando via Docker for Windows, mas num Linux ou num Mac, o resultado seria idêntico. Tudo que você precisa é open source: o .NET Core, o .NET CLI, um editor de texto (eu uso Vim ou VSCode), o MongoDB e o Docker.

O projeto está no meu Github, você pode dar uma olhada lá em giggio/MongoDbDotNetCore.

Conclusão

.NET Core já pode ser usado hoje em produção, desde que você não se prenda a um banco relacional. MongoDB é um dos melhores bancos de documentos do mercado e tem um excelente suporte à plataforma .NET. Considere no seu próximo projeto.

***

Este artigo foi produzido em parceria com a Lambda3. Leia outros conteúdos no blog da empresa: blog.lambda3.com.br