Você está na página 1de 9

.

Net e o Entity Framework

Para trabalhar com Entity Framework, devemos instalar:

ASP.NET e desenvolvimento Web


Desenvolvimento Multiplataforma com .Net Core

E dos componentes individuais:

ASP.NET e ferramentas de desenvolvimento web.


C# e VisualBasic.
Extensão do GitHub para o Visual Studio.

Projeto Switch
Foi criado um projeto de nome Switch com a estrutura Other Project Types > Visual Studio Solutions
> Blank Solution , ou seja, uma solução em branco. Dentro dele, foram criadas as seguintes New Solution
Folder :

Domain ( Com projeto do tipo .NetCore > Class Library de nome Switch.Domain )

Onde vai conter todas as classes entidades na pasta Entities , e ainda a pasta Enums onde vai ser
guardado todos os enums, interface e Services .

Tests (Com projeto do tipo .NetCore > Class Library de nome Switch.Domain.Tests )

Local onde terá todos os testes, inclusive de domain.

Infra

Onde terá duas Solution Folder , com toda a configuração do Entity Framework.

CrossCutting
Data: (Com projeto do tipo .NetCore > Class Library de nome Switch.Infra.Data )

Onde foram instalados os pacotes Nuget necessários: Microsoft.EntityFrameworkCore.Proxies ,


Microsoft.EntityFrameworkCore.Tools e Pomelo.EntityFrameworkCore.MySql .

Nela contém a pasta Config que vai conter toda configuração de cada campo da entidade. A pasta
Context , onde vai ter a classe que vai contar com a configuração com cada uma das classes do
domínio e a pasta Repositories onde nela vai estar implementada toda a inteligência para se
conectar com o banco de dados (Inserir, consultar).

Application (Com projeto do tipo .NetCore > Class Library de nome Switch.Application )

Através desse projeto que a API vai conseguir se comunicar com o Domain.
API (Com projeto do tipo .NetCore > ASP.NET CORE WEB APPLICATION de nome Switch.API )

Conterá toda aplicação ASP.NET WEB.

Presentation

Foi alterado o projeto para inicialização para o Switch.API clicando nele com o direito e clicando em
Set as StartUp Project.

Modelo de entidades do projeto

Primeira Entidade
Foi adicionado em Switch.Domain na pasta Entities a entidade Usuario :

using Switch.Domain.Enums;
using System;

namespace Switch.Domain.Entities {
   public class Usuario {
       public int Id { get; private set; }
       public string Nome { get; set; }
       public string Sobrenome { get; set; }
       public string Senha { get; set; }
       public DateTime DataNascimento { get; set; }
       public SexoEnum Sexo { get; set; }
       public string UrlFoto { get; set; }
  }
}

Onde SexoEnum é um Enum que especifica o sexo e está localizado no Switch.Domain.Enums :

namespace Switch.Domain.Enums {
   public enum SexoEnum {
       NaoDefinido = 1,
       Feminino = 2,
       Masculino = 3
  }
}

Adicionando contexto (SwitchContext)


A classe Context , deve obter herança da classe DbContext de Microsoft.EntityFrameworkCore .

using Microsoft.EntityFrameworkCore;
using Switch.Domain.Entities;

namespace Switch.Infra.Data.Context {

   public class SwitchContext : DbContext{

       /*Cria um DbSet do tipo Usuario, que é a nossa entidade criada.*/


       public DbSet<Usuario> Usuarios { get; set; }
       
       /*Criamos um construtor que recebe um DbContextOptions e passa ele pelo construtor
da classe base.*/
       public SwitchContext(DbContextOptions options) : base(options) {
      }
  }
}
Com isso, já é o suficiente para fazer o mapeamento do que existe na classe Usuario para o banco de dados
de forma por convenção, que não precisa fazer configuração explicita de cada propriedade de Usuario . O
problema dessa forma, é que não da pra setar o tamanho dos campos de cada propriedade na tabela, o
próprio EF faz isso.

Configurando o acesso ao DB na WEB API


O EF se encarrega de fazer o mapeamento e criar toda a estrutura e um schema novo no Mysql . Para isso,
precisamos criar uma string de conexão.

Para isso, adicionamos um arquivo do tipo Arquivo de Configurações do Aplicativo (.json) com nome
config.json no projeto Switch.API :

{
 "ConnectionStrings": {
   "SwitchDB": "Server=localhost;userid=root;password=admin;database=SwitchDB"
}
}

Definimos o nome da string que será referenciada no Startup.cs como SwitchDB . Server sendo o
localhost , o userid e o password que foi configurado no Mysql, e o database é o nome do Schema, que é
recomendado ser o mesmo nome da string de conexão ( SwitchDB ).

Após configurar, iremos no Startup.cs do mesmo projeto para configurar:

1. Devemos passar para a ConfigurationBuilder a string de conexão e atribuir a um objeto do tipo


IConfiguration .

//Declarando uma propriedade IConfiguration


IConfiguration Configuration { get; set; }

//Declarando um construtor que recebe um IConfiguration


public Startup(IConfiguration configuration) {
   //Cria um objeto do tipo ConfigurationBuilder e adiciona a File Json da string de
conexão
var builder = new ConfigurationBuilder().AddJsonFile("config.json");
   //Constroe ela dentro da propriedade IConfiguration
Configuration = builder.Build();
}

2. Vamos manipular o método ConfigureServices :


public void ConfigureServices(IServiceCollection services) {
   //Criamos uma variável conn pegando a string de conexão. Coomo o config.json foi
configurado na propriedade Configuration, ao usar o método abaixo, ele procura na
string de conexão a chava SwitchDB e retorna a string contendo a informação do
banco(User, Password)..
   var conn = Configuration.GetConnectionString("SwitchDB");
   
   /*
   No objeto trazido como parâmetro 'services', usamos o método .AddDbContext para
adicionar um contexto com o tipo SwitchContext criado no Switch.Infra.Context. Dentro
dela, especifica na função lambda o tipo de contexto que está trabalhando, nesse caso
o .UseLazyLoadingProxies que é o carregamento preguiçoso, e em seguida o .UseMysql
passando como primeiro parâmetro a string de conexão que foi obtido acima e no segundo
parâmetro uma função lambda passando uma string com o local do pacote que contem todos
os Assembly(pacotes e conexão) do entity Framework, que nosso caso está na
Switch.Infra.Data
   */
   services.AddDbContext<SwitchContext>(option => option.UseLazyLoadingProxies()
                            .UseMySql(conn, m =>
m.MigrationsAssembly("Switch.Infra.Data")) );

   //Por final, diz que está trabalhando com o AddMvcCore.


services.AddMvcCore();
}

Por final, teremos o Startup.cs de Switch.API assim:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Switch.Infra.Data.Context;
using Microsoft.EntityFrameworkCore;

namespace Switch.API {
   public class Startup {

       IConfiguration Configuration { get; set; }


       public Startup(IConfiguration configuration) {
           var builder = new ConfigurationBuilder().AddJsonFile("config.json");
           Configuration = builder.Build();
      }

       public void ConfigureServices(IServiceCollection services) {


           var conn = Configuration.GetConnectionString("SwitchDB");
           services.AddDbContext<SwitchContext>(option => option.UseLazyLoadingProxies()
                              .UseMySql(conn, m =>
m.MigrationsAssembly("Switch.Infra.Data")));

           services.AddMvcCore();
      }

       public void Configure(IApplicationBuilder app, IHostingEnvironment env) {


           if (env.IsDevelopment()) {
               app.UseDeveloperExceptionPage();
          }

           app.Run(async (context) => {


               await context.Response.WriteAsync("Hello World!");
          });
      }
  }
}

Mapeando a primeira classe


Agora iremos aplicar o modelo a base de dados. Para isso, utilizamos o migration. Agora, vamos abrir o
Package manager console e digitar Add-Migration nome , onde o nome serve somente para identificação.

Certifique-se que o Default Project será o pacote onde está o EF, no nosso caso, o Switch.Infra.Data e
que o Switch.API seja o projeto de startup.

Possa ser que ocorra um erro, pois a partir de um release do EF Core, foi necessário a inclusão do
pacote Microsoft.EntityFrameworkCore.Relational . Instale ele através do NuGet no pacote
Switch.Infra.Data com a mesma versão dos outros pacotes.

Um outro erro que pode acontecer, é o The configuration file config.json was not found onde fala
que não foi encontrado o arquivo config.json . Isso acontece porque no processo de compilação, deve-se
informar que o arquivo será copiado para o mesmo diretório de saída dos outros compilados do projeto. Para
resolver esse problema, clique com o direito encima do arquivo config.json , properties :
E deixar selecionado o Copy always , ou seja, copiar sempre.

Caso seja tudo configurado e o comando seja executado com êxito, o prompt retornará o seguinte resultado:

E após isso, será criado no projeto Switch.Infra.Data uma pasta Migrations com alterações no modelo.
Com a estrutura inicial do migrations, resta replicar tudo do migrations no banco de dados, com o comando
Update-database -Verbose onde o Verbose(Opcional) é somente para acompanhar os comandos que irão
ser executados.

Caso ocorra um erro do tipo Unable to connect to any of the specified Mysql hosts. verifique o
arquivo config.json e verifique se os dados estão corretos, além disso, verifique se o Mysql está
rodando.

Nesse momento, o banco será criado com o modelo aplicado.

Mapeamento por configuração


Até então, estávamos mapeando através de convenção, onde o próprio EF mapeava o tamanho e a definição
das classes para o banco de dados. Neste momento, iremos aprender como mapear por configuração, onde
o programador que seta o comportamento daquela entidade no bando de dados.

Para isso, devemos entender sobre FLUENT API: Um padrão de programação que permite o mapeamento
das entidades utilizando uma linguagem de programação. Em versões antigas de ORM, o mapeamento era
realizado em arquivos externos xml , e a partir do FLUENT API, fazemos isso através do C#.

Para trabalhar com o FLUENT API, devemos ter acesso ao ModelBuilder(Construtor de modelos).
Para configurarmos explicitamente, iremos adicionar na pasta Config de Switch.Infra.Data uma classe
chamada UsuarioConfiguration com toda a configuração explicita de Usuario :

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Switch.Domain.Entities;

namespace Switch.Infra.Data.Config {
   class UsuarioConfiguration : IEntityTypeConfiguration<Usuario> {

       public void Configure(EntityTypeBuilder<Usuario> builder) {

           //O .HasKey define a chave primária


           builder.HasKey(u => u.Id);
           
           /*
           Configurando cada componente da entidade.
          .HasMaxLength() - É o tamanho máximo do campo, no caso, 400 caracteres.
          .IsRequired() - Afirma que o campo é obrigatório.
          .HasDefaultValue() - Coloca um valor padrão.
          .HasColumnName() - Nome do atribuito na tabela (Caso não tenha, o nome é o
mesmo nome do atributo)
           */
           builder.Property(u => u.Nome).HasMaxLength(400).IsRequired();
           builder.Property(u => u.Sobrenome).HasMaxLength(400).IsRequired();
           builder.Property(u => u.Senha).HasMaxLength(400).IsRequired();
           builder.Property(u => u.UrlFoto).HasMaxLength(400).IsRequired();
           builder.Property(u => u.DataNascimento).IsRequired();
           builder.Property(u => u.Sexo).IsRequired();

      }
  }
}

E classe recebe herança da IEntityTypeConfiguration<Usuario> , logo, ela pede a implementação do


método Configure , onde nela vai ter todas as configurações de cada atributo ~ campo DB.

O método Configure recebe um EntityTypeBuilder como mencionado na imagem, e a partir dela existem
os métodos também descrito na imagem.

Após a configuração, devemos aplicar ao banco de dados com Add-Migration e Update-database -Verbose .

Toda vez que faz um migration a tabela é refeita, excluindo todos os dados antes existentes

Você também pode gostar