EF Core - Sistema de Vendas : Usando a Fluent API
Neste artigo eu vou mostrar como usar os recursos da Fluent API com EF Core em um projeto Console. |
Ao trabalhar com a abordagem Code First usando o Entity Framework o
comportamento padrão é mapear suas classes POCO para tabelas usando um
conjunto de convenções nativas do EF. Às vezes, no entanto, você não pode ou não
quer seguir essas convenções e precisa mapear entidades para algo diferente do
que as convenções ditam.
Existem duas maneiras de realizar a configuração e o mapeamento no EF quando
você não deseja seguir as convenções padrão: Data
Annotations e Fluent API.
1- Data Annotations - Utiliza atributos para realizar o
mapeamento e configuração;
2- Fluent API - Fornece mais funcionalidades que o Data Annotations
Na abordagem Code First a Fluent API é mais
acessada sobrescrevendo o método OnModelCreating no seu
DbContext.
A Fluent API suporta os seguintes tipos de mapeamentos:
Mapeamento | Para o Banco de dados |
---|---|
Model-wide Mapping |
- Define o esquema padrão - Define as convenções padrão |
Entity Mapping |
- Para única ou múltiplas tabelas e esquema - Para Tipo Completo - Para hierarquia de herança |
Property Mapping |
- Para Coluna, Nome da coluna, tipo de coluna,coluna Nullabe(anulável) ou não NULL coluna, - O tamanho das colunas, ordem das colunas - Para coluna concorrência - Para coluna chave estrangeira - Para configurar relacionamentos |
Neste artigo eu vou mostrar como usar a Fluent API para definir o mapeamento entre as classes do domínio da aplicação e as tabelas do banco de dados.
Recursos usados:
SQL Server
EF Core 5.0
Definindo o cenário
Vamos simular um cenário para um sistema de Vendas focando nos pedidos onde temos as seguintes entidades definidas: Pedidos, Itens, Clientes e Produtos
Na figura abaixo temos a representação das entidades e seus atributos e também do relacionamento entre as entidades.
Relacionamentos:
A entidade Pedidos possui um relacionamento de um para muitos para a entidade Itens
A entidade Clientes possui um relacionamento de um para muitos para a entidade Pedidos
A entidade Produtos possui um relacionamento de um para muitos para a entidade Itens
Essa seria uma visão a nível de entidades, conjunto de entidade, atributos e relacionamentos do modelo entidade relacionamento (MER) que esta baseado em uma percepção do mundo real para expressar um sistema de vendas.
Vamos partir deste cenário mas vamos usar a abordagem Code-First do EntityFramework Core e nesta abordagem ao invés de iniciar criando o banco de dados vamos nos concentrar no domínio da aplicação e vamos começar criando as classes e definir as propriedades das classes que representam os atributos e também vamos definir as associações entre as classes que representam os relacionamentos.
A seguir vamos aplicar o Migrations do EF Core para criar o banco de dados e as tabelas relacionadas com as classes definidas no domínio.
Assim usando a abordagem Code-First do EF Core vamos tratar com:
Classes do domínio
Criar as propriedades nas classes
Definir as associações entre as classes (Propriedades de navegação)
Aplicar o recurso Migrations para criar o banco de dados e as tabelas mapeadas
O mapeamento entre as classes e suas propriedades e as tabelas serão feitas usando a Fluent API.
Como nosso objetivo é focar na utilização da Fluent API vamos criar um projeto do tipo Console e definir neste projeto as classes, configurações e mapeamentos.
Em um projeto usando as boas práticas usaríamos uma arquitetura desacoplada criando projetos separados conforme a responsabilidade de cada projeto. A seguir, apenas para constar, temos uma sugestão de arquitetura que pode ser usada.
Domain - Contém as entidades do domínio da aplicação e validações relacionadas;
Application - Contém as interfaces e casos de uso da aplicação que permitem acessar o domínio e implementam a lógica de negócio;
Infrastructure - Contém os recursos para definir a lógica de acesso a dados, repositórios, etc.;
CrossCutting - Contém as definições e configurações dos serviços e recursos usados nos projetos da solução;
Pedidos - Representa a camada de apresentação que vai interagir com os demais projetos;
Os projetos Domain, Application, Infrastructure e CrossCutting seriam projetos do tipo Class Library (.NET 5.0) e o projeto Pedidos seria o projeto do tipo Console (.NET 5.0).
Criando o projeto no VS 2019
Abra o VS 2019 e clique em New Project;
A seguir selecione o template Console Application e clique em Next;
Informe o nome do projeto Vendas e sua localização.
A seguir selecione o Target Framework como .NET 5.0 (Current) conforme figura abaixo:
Clique em Create.
Vamos iniciar incluindo as referências aos seguintes pacotes do EF Core neste projeto:
Para incluir os pacotes use o menu Tools->..-> Manage Nuget Packages for Solution e na guia Browse selecione e instale os pacotes ou abra a janela Package Manager Console e digite o comando: install-package <nome-pacote>
Pronto já temos o projeto Console criado e pronto para ser usado usando o EF Core.
No projeto vamos criar uma pasta chamada Entities e nesta pasta criar as entidades que representam o nosso modelo de domínio representando pelas classes:
Vamos usar também duas enumerações definidas nos arquivos : StatusPedido e TipoFrete
Aqui devemos decidir quais as propriedades e comportamentos nosso domínio vai possuir. Para não tornar o exemplo muito longo e maçante eu vou definir um modelo de domínio bem simples.
A seguir temos o código das entidades e das enumerações:
1- Pedido
using System;
using System.Collections.Generic;
namespace Domain.Entities
{
public class Pedido
{
public int PedidoId { get; set; }
public int ClienteId { get; set; }
public DateTime DataPedido { get; set; }
public DateTime DataEntrega { get; set; }
public TipoFrete Frete { get; set; }
public StatusPedido Status { get; set; }
public ICollection<Item> Itens { get; set; }
public Cliente Cliente { get; set; }
}
}
|
2- Cliente
using System.Collections.Generic;
namespace Domain.Entities
{
public class Cliente
{
public int ClienteId { get; set; }
public string Nome { get; set; }
public string Email { get; set; }
public string Telefone { get; set; }
public string Cep { get; set; }
public string Cidade { get; set; }
public string Estado { get; set; }
public ICollection<Pedido> Pedidos { get; set; }
}
}
|
3- Item
public class Item
{
public int ItemId { get; set; }
public int PedidoId { get; set; }
public int ProdutoId { get; set; }
public int Quantidade { get; set; }
public decimal Preco { get; set; }
public Pedido Pedido { get; set; }
public Produto Produto { get; set; }
}
|
4- Produto
using System.Collections.Generic;
namespace Domain.Entities
{
public class Produto
{
public int ProdutoId { get; set; }
public string Nome { get; set; }
public string Descricao { get; set; }
public decimal Preco { get; set; }
public bool Ativo { get; set; }
public ICollection<Item> Itens { get; set; }
}
}
|
5- StatusPedido
public enum StatusPedido
{
Analise,
Finalizado,
Entregue
}
|
6- TipoFrete
public enum TipoFrete
{
CIF,
FOB,
SemFrete
}
|
Incluindo um Class Diagram em nosso projeto iremos obter o seguinte diagrama exibindo os objetos criados no projeto Domain:
Na segunda parte do artigo vamos continuar definindo o mapeamento das classes usando a Fluente API.
"Voz do que clama no deserto: Preparai o caminho do Senhor; endireitai no ermo
vereda a nosso Deus.
Todo o vale será exaltado, e todo o monte e todo o outeiro será abatido; e o que
é torcido se endireitará, e o que é áspero se aplainará."
Isaías 40:3,4
Referências: