ASP .NET Core - Usando o EF Core em um projeto separado - I |
Neste artigo vou mostrar como usar e configurar o EF Core em um projeto separado na criação de uma aplicação ASP .NET Core MVC. |
Ao criar uma aplicação ASP .NET Core MVC usando o template padrão a abordagem mais comumente usada é definir a classe de contexto, as entidades e as referências no mesmo projeto.
Fazendo assim estamos criando um forte acoplamento entre a camada de apresentação, representada pela aplicação MVC e a ferramenta ORM, no caso o EF Core. Assim, se você resolver mudar o ORM vai afetar também a camada de apresentação.
Uma boa prática e separar a configuração do EF Core em um projeto diferente criando assim o que podemos chamar de uma camada de acesso aos dados ou DAL (Data Access Layer).
Para mostrar isso neste artigo vamos criar uma aplicação ASP .NET Core MVC usando a arquitetura em 4 camadas onde vamos ter os seguintes projetos:
Como exemplo vamos criar um projeto que gerencia as informações de receitas.
Como vamos usar as versões do .NET Core 5.0, EF Core 5.0 e ASP .NET Core 5.0 a primeira coisa a fazer é atualizar o seu ambiente para o .NET 5.
Para isso acesse os links abaixo e faça o download e a instalação das seguintes pacotes:
Para gerenciar as informações vamos usar o EF Core 5.0 na abordagem Code-First.
Mãos a obra..
Criando a solução e os projetos
Vamos iniciar criando uma Blank Solution chamada Receitas.
A seguir vamos criar os projetos individuais na solução.
No menu File selecione Add -> New Project, selecione o template Class Library(.NET Standard) e informe o nome Receitas.Domain;
A seguir vamos repetir o procedimento acima e criar os projetos do tipo Class Library(.NET Standard) nomeados como Receitas.Infra e Receitas.Application.
Para criar o projeto Web selecione o menu File-> Add-> New Project e selecione o template ASP .NET Core Web Application e informando o nome Receitas.Mvc
Para tornar mais simples o cenário não vamos habilitar a autenticação do usuário.
A seguir escolha o template Web Application(Model-View-Controller) e clique em Create;
Ao final teremos a solução com projetos conforme abaixo:
Para concluir vamos definir as referências entre os projetos criados da seguinte forma:
Para incluir uma referência aos projetos Receitas.Domain e Receitas.Application no projeto Infra, clique com o botão direito do mouse sobre o projeto Receitas.Infra e selecione Add-> Project Reference;
Selecione o projeto Receitas.Domain e o projeto Recietas.Application e clique em OK;
Repita o procedimento para o projeto Receitas.Mvc e marque os dois projetos: Domain e Infra:
Repita o procedimento para o projeto Receitas.Application marcando apenas o projeto Domain.
Para concluir vamos alterar a definição do <TargetFramework> dos projetos Receitas.Application, Receitas.Domain e Receitas.Infra de .netstandard2.0 para .net5.0 conforme abaixo:
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
Criando o modelo de domínio
Vamos iniciar criando as entidades que representam o nosso modelo de domínio, e, no nosso exemplo vamos ter apenas uma entidade chamada Receita.
No projeto Receitas.Domain vamos criar a pasta Entities e nesta pasta vamos criar a classe Receita :
public class Receita
{ public int Id { get; set; } public string Nome { get; set; } public string Preparo { get; set; } public int Tempo { get; set; } public string Ingredientes { get; set; } public string Imagem { get; set; } } |
Temos aqui uma classe POCO com 6 propriedades definida como um modelo anêmico que funciona praticamente como um DTO.
Criando a infraestrutura com o EF Core
No projeto Receitas.Infra iniciar vamos iniciar a definição da lógica de acesso aos dados criando uma pasta Context no projeto e nesta pasta vamos criar a classe AppDbContext.
Antes de definir o código da classe vamos incluir neste projeto os seguintes pacotes:
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Clique com o botão direito do mouse sobre Dependencies e selecione Manage Nuget Packages;
Selecione a guia Browse e instale cada um dos pacotes mencionados. Ao final teremos o resultado abaixo no projeto:
Agora podemos definir o código da classe AppDbContext que representa o contexto da nossa aplicação onde definimos o mapeamento ORM e as opções para obter o provedor do banco de dados e a string de conexão.
using Microsoft.EntityFrameworkCore; using Receitas.Domain.Entities;
namespace Receitas.Infra.Context public DbSet<Receita> Receitas { get; set; }
protected override void OnModelCreating(ModelBuilder
modelBuilder)
modelBuilder.Entity<Receita>()
modelBuilder.Entity<Receita>()
modelBuilder.Entity<Receita>()
modelBuilder.Entity<Receita>() |
Vamos entender o código acima:
1- Definimos as opções do DbContext no construtor usando DbContextOptions onde vamos injetar o contexto no contêiner IoC e definir a string de conexão e o provedor com o banco de dados;
2- Definimos o mapeamento ORM usando a propriedade DbSet<T> mapeando a entidade Receita para tabela Receitas;
3- No método OnModelCreating usamos a Fluent API para definir o tamanho máximo para as propriedades do tipo string;
4- Usamos o método HasData para popular a tabela do banco de dados com dados de duas receitas na aplicação do Migrations;
Agora só precisamos definir a string de conexão com o banco de dados SQL Server no arquivo appsettings.json do projeto Receitas.Mvc :
{ "ConnectionStrings": { "DefaultConnection": "Data Source=desktop-bhp8771\\sqlexpress;Initial Catalog=ReceitasDB;Integrated Security=True" }, "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "AllowedHosts": "*" } |
E a seguir vamos definir a configuração do contexto como um serviço no projeto Receitas.Infra.
Para isso vamos criar a classe DependencyInjection e o método de extensão AddInfrastructure() :
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Receitas.Infra.Context;
namespace Receitas.Infra
{
public static class DependencyInjection
{
public static IServiceCollection AddInfrastructure(this IServiceCollection services,
IConfiguration configuration)
{
services.AddDbContext<AppDbContext>(options =>
options.UseSqlServer(
configuration.GetConnectionString("DefaultConnection"),
b => b.MigrationsAssembly(typeof(AppDbContext)
.Assembly.FullName)));
services.AddDatabaseDeveloperPageExceptionFilter();
return services;
}
}
}
|
Agora precisamos definir no projeto Receitas.Mvc no método ConfigureServices do arquivo Startup a utilização deste método de extensão e assim disponibilizar a definição do serviço do contexto para a aplicação MVC.
...
public void ConfigureServices(IServiceCollection services)
{
services.AddInfrastructure(Configuration);
services.AddControllersWithViews();
}
...
|
Para concluir precisamos disponibilizar uma instância do arquivo de contexto AppDbContext para o projeto MVC.
Vamos alterar o código do arquivo Program conforme abaixo:
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Receitas.Infra.Context;
using System;
namespace Receitas.Mvc
{
public class Program
{
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<AppDbContext>();
context.Database.Migrate();
}
catch (Exception ex)
{
var logger = scope.ServiceProvider.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "Ocorreu um erro na Migração ou alimentação dos dados.");
}
}
host.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
|
Neste código , quando a aplicação MVC for inicializada iremos obter o instância do arquivo de contexto.
Agora podemos aplicar o Migrations.
No Visual Studio acione o menu Tools-> Nuget Package Manager -> Package Manager Console ;
E na janela do Package Manager Console selecione o projeto Receitas.Infra e defina os comandos do Migrations:
add-migration
'MigracaioInicial' -Context AppDbContext
update-database
Agora vamos emitir o comando update-database para criar o banco de dados e a tabela Receitas:
Abrindo o SQL Server Management Studio podemos confirmar a criação da tabela Receitas contendo dois registros:
Dessa forma nosso projeto MVC não possui referências ao EF Core e todas as
referências e a migrações estão no projeto de infraestrutura.
Na próxima parte do artigo vamos continuar criando o controlador e as views para exibir os dados das receitas.
"Bendito o Deus e Pai de nosso Senhor
Jesus Cristo, o qual nos abençoou com todas as bênçãos espirituais nos lugares
celestiais em Cristo; Como também nos elegeu nele antes da fundação do
mundo, para que fôssemos santos e irrepreensíveis diante dele em amor;"
Efésios 1:3,4
Referências:
EF Core - Iniciando com o Entity Framework Core
Core - Usando o EF Core com Windows Forms ...
ASP .NET Core - Acessando dados com Entity ...
EF Core - Conceitos Básicos - Macoratti
EF Core - Usando a abordagem DataBase First ..
EF Core 2.0 - Scaffolding DbContext e Models .
Curso Entity Framework Core 2.0 - Vídeo Aulas