EF Core - Usando um Banco de dados In-Memory
 Neste artigo veremos como usar o Entity Framework Core (EF Core) como banco de dados In-Memory para o ASP .NET Core.

Uma das novidades do EF Core é a adição de um provedor de dados in-memory que torna possível prototipar aplicações e escrever testes sem ter que configurar um banco de dados local ou externo. Assim, quando você terminar os testes e estiver pronto para trocar para o seu banco de dados de produção, basta simplesmente trocar o provedor usado.

Neste artigo eu vou mostrar como configurar o EF Core para usar o provedor in-Memory e usá-lo em uma aplicação ASP .NET Core.

Neste artigo eu vou usar o VS 2017 para criar uma aplicação ASP .NET Core usando o template Web API, mas você pode usar o VS Code ou VS for Mac conforme eu mostrei nestes artigos:

  1. ASP .NET Core - Criando uma aplicação ASP .NET Core ... - Macoratti

  2. ASP .NET Core - Acessando o banco de dados PostGreSQL no MacOS com VS for Mac - I

  3. ASP .NET Core - Criando uma aplicação ASP .NET Core MVC com o VS 2017 - I

Para acompanhar este artigo você precisa ter instalado o Visual Studio Community 2017 com os seguintes workloads instalados:

Recurso utilizados :

Criando o projeto ASP .NET Core

Abra no VS 2017 e no menu File clique em New Project;

A seguir selecione o template Visual C# -> .NET Core e marque ASP .NET Core Web Application (.NET Core);

Informe o nome AspnetCore_EFCoreInMemory e clique em OK;

A seguir selecione o template Web API, sem autenticação e sem usar o suporte ao Docker.

Instalando o Entity Framework Core In-Memory no projeto

Vamos agora instalar o EF Core em nosso projeto via Nuget. No menu Tools-> Nuget Package Manager clique em Manage Nuget Packages for Solution;

Selecione o pacote para Microsoft.EntityFrameworkCore.InMemory e instale no projeto:

Definindo o modelo de entidades e o contexto

A seguir vamos criar uma pasta Models no projeto e definir um modelo de entidades e o contexto para testar o EF Core In-Memory.

Vamos criar as seguintes classes na pasta Models:

1 - Usuario.cs - Representa um usuário que pode ter uma lista de posts

using System.Collections.Generic;

namespace AspnetCore_EFCoreInMemory.Models
{
    public class Usuario
    {
        public string Id { get; set; }
        public string Nome { get; set; }
        public string Email { get; set; }
        public List<Post> Posts { get; set; }
    }
}

2- Post.cs - Representa um post feito por um usuário

namespace AspnetCore_EFCoreInMemory.Models
{
    public class Post
    {
        public string Id { get; set; }
        public string Usuariod { get; set; }
        public string Conteudo { get; set; }

        public Usuario Usuario { get; set; }
    }
}

3 - ApiContext.cs - Representa o contexto das entidades e herda da classe DbContext definindo o mapeamento entre as entidades e as tabelas e a conexão com o banco de dados:

using Microsoft.EntityFrameworkCore;

namespace AspnetCore_EFCoreInMemory.Models
{
    public class ApiContext : DbContext
    {
        public ApiContext(DbContextOptions<ApiContext> options)
          : base(options)
        {}

        public DbSet<Usuario> Usuarios { get; set; }
        public DbSet<Post> Posts { get; set; }
    }
}

Essas classes representam os dados que serão salvos e carregados a partir do banco de dados. Temos aqui um relacionamento um-para-muitos entre Usuarios e Posts onde um Post pertence a um Usuario, e um Usuario pode ter muitos Posts.

As propriedades Posts e Usuarios serão automaticamente preenchidas pelo EF Core.

Configurando o EF Core In-Memory na aplicação

Vamos agora conectar este contexto do banco de dados com a nossa aplicação usando o provedor in-memory.

Abra a classe Startup.cs do projeto e no método ConfigureServices inclua o código a seguir:

using AspnetCore_EFCoreInMemory.Models;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

        ...

       // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<ApiContext>(opt => opt.UseInMemoryDatabase());

            // Add framework services.
            services.AddMvc();
        }
       ...

Incluindo dados de testes

Vamos agora incluir alguns dados de testes no banco de dados in-memory quando a aplicação for inicializada.

Para isso vamos abrir o arquivo Startup.cs e incluir o código abaixo no método Configure:

            ...
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();

            var context = app.ApplicationServices.GetService<ApiContext>();
            AdicionarDadosTeste(context);

            app.UseMvc();
        }
        ...

Agora vamos incluir o método AdicionarDadosTeste() no método Configure:

       private static void AdicionarDadosTeste(ApiContext context)
        {
            var testeUsuario1 = new Models.Usuario
            {
                Id = "usuario1",
                Nome = "Macoratti",
                Email = "macoratti@yahoo.com"
            };

            context.Usuarios.Add(testeUsuario1);

            var testePost1 = new Models.Post
            {
                Id = "post1",
                UsuarioId = testeUsuario1.Id,
                Conteudo = "Primeiro Post(post1) do Usuario : usuario1"
            };

            context.Posts.Add(testePost1);

            context.SaveChanges();
        }

Criando a Web API para retornar os dados

Para poder retornar os dados podemos criar uma Web API definindo um controlador na pasta Controllers para o nosso modelo de entidades e contexto.

Nota: Poderíamos ter criado um projeto MVC com páginas usando Scaffolding.

Clique com o botão direito do mouse sobre a pasta Controllers e a seguir clique em Add Controller;

Marque a opção Minimal Dependencies e clique em Add;

Repita o procedimento e marque agora a opção API Controller - Empty  e clique em Add:

Informe o nome UsuariosController e clique em Add.

Defina o código abaixo no arquivo UsuariosController:

using AspnetCore_EFCoreInMemory.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Threading.Tasks;

namespace AspnetCore_EFCoreInMemory.Controllers
{
    [Produces("application/json")]
    [Route("api/Usuarios")]

    public class UsuariosController : Controller
    {
        private readonly ApiContext _context;

        public UsuariosController(ApiContext context)
        {
            _context = context;
        }

        public async Task<IActionResult> Get()
        {
            var usuarios = await _context.Usuarios
                                 .Include(u => u.Posts)
                                 .ToArrayAsync();

            var resposta = usuarios.Select(u => new
            {
                nome =  u.Nome,
                email = u.Email,
                posts = u.Posts.Select(p => p.Conteudo)
            });

            return Ok(resposta);
        }
    }
}

Vamos entender o código:

- Temos um objeto ApiContext requisitado a partir do serviço de injeção de dependência no construtor que expõe a rota HTTP GET retornando todos os usuários e seus posts armazenados no banco de dados.

- No método Get(), o método Include() informa explicitamente ao EF Core para carregar os posts dos usuários com seus outros detalhes. O EF Core sabe que o campo UsuarioId no modelo Post representa uma chave estrangeira para o relacionamento entre Usuarios e Posts.

- Depois que os usuários e posts são retornados de forma assíncrona do banco de dados, o array é projetado (usando Select) incluindo somente os campos que precisamos para retornar um JSON mais enxuto.

Testando a aplicação

Para testar a aplicação execute o projeto e digite na URL a rota definida no mapeamento : http://localhost:4333/api/usuarios

Ao final do processamento teremos o seguinte resultado:

E assim acabamos de criar uma aplicação usando o Entity Framework Core In-Memory, após testar basta alterar o provedor usado no projeto para o do seu banco de dados. Além disso você também pode realizar testes de integração usando este recurso.

Pegue o projeto completo aqui : AspnetCore_EFCoreInMemory.zip

E agora, filhinhos, permanecei nele(Jesus); para que, quando ele se manifestar, tenhamos confiança, e não sejamos confundidos por ele na sua vinda1 João 2:28


Referências
:


José Carlos Macoratti