Entity Framework - Criando Relacionamentos entre entidades (Code First)

  Neste artigo vou mostrar como podemos usar o EF6 na abordagem Code-First para definir o relacionamento entre as entidades de um modelo de entidades.


O Entity Framework permite trabalhar usando 3 abordagens :
  • DataBase First
  • Code First
  • Model First

Na abordagem Code-First do Entity Framework podemos criar um modelo como uma classe simples e, em seguida, o banco de dados será criado a partir do modelo de domínio ou classe de entidade. Assim no Code-First o banco de dados é criado a partir da classe.

Vantagens da abordagem Code-First:

• Você dessenvolve seu modelo de de domínio sem ter que abrir um designer ou definir um arquivo de mapeamento XML;
• Permite definir os objetos do seu modelo, simplesmente escrevendo "classes simples", sem classes de base necessárias;
• Usando a abordagem da "convenção sobre configuração" ela permite a persistência do banco de dados sem configurar explicitamente nada;
• Substituindo a persistência baseada em convenções e usando uma API de código fluente podemos personalizar completamente o mapeamento de persistência;


Como eu já escrevi muitos artigos abordando o funcionamento do EF este artigo será mais prático. Neste artigo vamos criar as tabelas e o banco de dados usando a abordagem Code-Frist e vamos aprender como podemos criar entidades e definir relacionamentos entre as entidades.

Usando o Code-First temos duas opções para criar o relacionamento entre as entidades:

1. Data Annotations
2. Fluent API


Cada uma tem suas vantagens e desvantagens, e, neste artigo eu vou usar Data Annotations.

Recursos Usados:

  • Visual Studio 2017 Community
  • Entity Framework 6

Criando o projeto e instalando o EF 6

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

A seguir selecione o template Visual C# -> Windows Classic Desktop -> Console App (.NET Framework);

Informe o nome EF6_Relacionamentos e clique no botão OK;

Abra uma janela para o Nuget Package Manager e digite o comando : Install-Package EntityFramework -Version 6.1.3

Criando uma tabela e um banco de dados

Crie uma chamada Model no projeto e a seguir inclua uma classe chamada Aluno nesta pasta com o seguinte código :

    public class Aluno
    {
        public int Id { get; set; }
        public string Nome { get; set; }
        public int Idade { get; set; }
    }

Temos aqui uma classe simples que o EF vai usar para criar a tabela do banco de dados. Essa classe representa a entidade do domínio e não tem nenhuma referência ao banco de dados.

Agora precisamos criar uma classe de contexto que vai representar uma sessão com o banco de dados e que deve herdar da classe DbContext.

Crie a classe AlunoDbContext na pasta Model com o código abaixo:

using System.Data.Entity;
namespace EF6_Relacionamentos.Model
{
    public class AlunoDbContext : DbContext
    {
        public AlunoDbContext() : base()
        {}

        public DbSet<Aluno> Alunos { get; set; }
    }
}

Neste código fizemos o seguinte :

Nota:  Se você não definir a propriedade DbSet<T> não será criada nenhuma tabela.

Vamos agora definir o código na classe Program.cs que vai criar o banco de dados e a tabela Alunos e a seguir vai incluir a informação para um aluno.

using EF6_Relacionamentos.Model;
using System;
using System.Linq;
namespace EF6_Relacionamentos
{
    class Program
    {
        static void Main(string[] args)
        {
            CriaAluno();
            Console.WriteLine("Aluno criado com sucesso...");
            Console.WriteLine("Acessando os dados dos Alunos...");       
            AlunoDbContext db = new AlunoDbContext();
            var resultado = from aluno in db.Alunos select aluno;
            foreach (var a in resultado)
            {
                Console.WriteLine(a.Nome + " "   + a.Idade.ToString());
            }
            Console.ReadKey(true);
        }
        static void CriaAluno()
        {
            Aluno aluno = new Aluno
            {
                Id = 1,
                Idade = 12,
                Nome = "Macoratti"
            };
            AlunoDbContext db = new AlunoDbContext();
            db.Alunos.Add(aluno);
            db.SaveChanges();
        }
    }
}

A figura acima mostra o resultado da execução do código ao lado.

Observe que os dados exibidos foram os dados informados no código ao lado:

  • Id = 1
  • Idade = 12
  • Nome = Macoratti

Vamos entender o que aconteceu por 'trás dos panos'...

Criamos uma instância do contexto e incluímos o novo aluno no contexto usando a instrução Add() ao chamar o método SaveChanges() as informações são salvas no banco de dados que será criado por padrão seguindo as convenções já mencionadas.

Abrindo o SQL Server Object Explorer no menu View iremos encontrar o seguinte resultado no servidor (localDb)\MSSSQLLocalDB (SQL Server....) :

Embora o banco de dados e a tabela tenham sidos criados conforme estavamos esperando o nome da tabela criada foi Alunoes e não Alunos. Por quê ?

A convenção é colocar o nome da tabela como sendo o plural do nome da entidade e a nossa entidade foi definida com o nome Aluno e o plural na língua inglesa para palavras terminadas em o acresenta es.

Mas como resolver isso ?

Vamos agora resolver esse problema do nome da tabela e também definir um nome customizado para o banco de dados.

Para atribuir um nome para o banco de dados vamos definir uma string de conexão com o nome do banco de dados desejado.

Para isso vamos incluir no arquivo App.Config a string de conexão conforme abaixo:

  <connectionStrings>
    <add name="ConexaoSQLServerEscolaDemo" connectionString="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=EscolaDemo;Integrated Security=True;MultipleActiveResultSets=true" providerName="System.Data.SqlClient"/>
  </connectionStrings>

Nome da string de conexão é ConexaoSQLServerEscolaDemo e o nome do banco de dados é EscolaDemo.

Agora precisamos passar a informação da string de conexão para o construtor da classe do contexto : AlunoDbConext,  conforme mostrado abaixo:

using System.Data.Entity;
namespace EF6_Relacionamentos.Model
{
    public class AlunoDbContext : DbContext
    {
        public AlunoDbContext() : base("name=ConexaoSQLServerEscolaDemo")
        { }
        public DbSet<Aluno> Alunos { get; set; }
    }
}

Isso resolve o problema do nome e da localização do banco de dados. E o nome da tabela ?

Para definir o nome da tabela customizada basta incluir um Data Annotations na classe Aluno definindo explicitamente que desejamos que o nome da tabela seja Alunos.

Nota : Para saber detalhes sobre Data Annotations veja este artigo : Entity Frameweork 4 - Usando Data Annotations - Macoratti

using System.ComponentModel.DataAnnotations.Schema;
namespace EF6_Relacionamentos.Model
{
    [Table("Alunos")]
    public class Aluno
    {
        public int Id { get; set; }
        public string Nome { get; set; }
        public int Idade { get; set; }
    }
}

Observe que usamos o namespace System.ComponentModel.DataAnnotations.Schema; para poder usar este recurso.

Podemos executar novamente o projeto. (Não esqueça de excluir o banco de dados criado pelo código anterior)

Como vemos, agora sim temos o resultado final exatamente como esperávamos.

Poderíamos obter o mesmo resultado executando o Migrations do Entity Framework.

O Code First funciona muito bem e é muito fácil de usar. Mas ele não tem uma característica importante, o tratamento das alterações do esquema de banco de dados (adicionar/remover/modificar colunas, tipos de dados, restrições, etc.) relacionadas com as alterações feitas no modelo de entidades.

Usando o Code First quando você altera o modelo de entidades gerado você tem que recriar o seu banco de dados novamente acarretando assim perda dos dados ou tem que gerar scripts SQL para manualmente refletir as alterações no banco de dados se não quiser perder os dados.

O Migrations veio para suprir a falta deste recurso no Code First. Usando o recurso MIgrations do Entity Framework podemos realizar alterações em nosso modelo de entidades e ter a atualização automática do banco de dados refletindo essas mudanças.

Para saber mais sobre o Migrations veja este artigo : Entity Framework - Usando o recurso Code First - Migrations - Macoratti

Em outro artigo vamos ver como definir um relacionamento um-para-um.

Eu sou a videira, vós as varas; quem está em mim, e eu nele, esse dá muito fruto; porque sem mim nada podeis fazer. 
João 15:5

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

  Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Referências:


José Carlos Macoratti