Entity Framework Code First
Do Carlos dos Santos
Março 2012
O Entity Framework faz uma ponte entre as classes POCO e o banco de dados utilizando um container que chamamos de Contexto. O contexto é o responsável por mapear as nossas classes com o banco de dados e também por informar ao engine quem é o banco de dados, através da string de conexão, e isto é o que mais me agrada no Code First, você precisa trocar somente a string de conexão para mudar de banco. Nenhum tipo de alteração no código é necessária.
Instalando o Entity Framework Code First
Antes de começarmos a escrever as classes, precisamos instalar o Entity Framework CodeFirst, que é basicamente composto pela EntityFramework.DLL. Faremos isto isando o NuGet, que é um instalador de pacotes para o Visual Studio. Se você ainda não o possui, vá até o Extension Manager do Visual Studio (Tools/Extension Manager) e instale.
Depois de instalado o NuGet, vá em Tools/Library Package Manager/Package Manager Console. Isto vai abrir o gerenciador do NuGet.
Agora digite o comando: Install-Package EntityFramework dentro do console, isto irá instalara o EF CodeFirst e suas dependências.
Criando um projeto com o EntityFramework CodeFirst
Vamos criar uma classe de contexto que chamaremos de Contexto.cs, esta classe irá herdar de DbContext e nela iremos mapear nossas tabelas.
1: using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.Text;
5: using System.Data.Entity;
6:
7: namespace EFCodeFirst
8: {
9: public class Contexto : DbContext
10: {
11: public DbSet<Grupo> Grupo { get; set; }
12: public DbSet<Produto> Produto { get; set; }
13: }
14: }
O segredo aqui é o DBSet<>, pois ele faz o mapeamento da nossa classe para o banco e vincula a um objeto, que utilizaremos para fazer as operações com o BD.
Veja o código da classe Grupo
1: using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.Text;
5: using System.ComponentModel.DataAnnotations;
6:
7: namespace EFCodeFirst
8: {
9: [Table("Grupo")]
10: public class Grupo
11: {
12: public int ID { get; set; }
13: [Required(ErrorMessage="Nome não pode ser branco.")]
14: public string Nome { get; set; }
15:
16: public virtual IQueryable<Produto> Produtos { get; set; }
17: }
18: }
E da classe Produto
1: using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.Text;
5: using System.ComponentModel.DataAnnotations;
6:
7: namespace EFCodeFirst
8: {
9: [Table("Produto")]
10: public class Produto
11: {
12: public int ID { get; set; }
13: [Required(ErrorMessage="Nome não pode ser branco.")]
14: public string Descricao { get; set; }
15: public int GrupoID { get; set; }
16:
17: [ForeignKey("GrupoID")]
18: public virtual Grupo Grupo { get; set; }
19: }
20: }
No CodeFirst podemos controlar todos os aspectos do mapeamento das classes com o banco de dados, desde o nome da tabela no banco, obrigatoriedade dos campos, tamanho, etc.
Na classe Grupo, eu determinei o nome da tabela no banco de dados (linha 9), ou seja, podemos ter um nome para a classes e outro para a tabela no banco de dados. Informei também que o nome não pode ser banco e vinculei uma mensagem, que pode ser usada em projetos MVC e WPF (linha 13). Finalmente criei o relacionamento entre Grupo e Produto (linha 16).
Na classe Produto, eu determinei também o nome da tabela no banco de dados, e o campo obrigatório. Fiz também o relacionamento com a tabela grupo através do campo GrupoID (linhas 15 e 17,18).
O EF identifica também automaticamente as chaves primárias das tabelas, desde que você as chame por ID ou nome_da_tabelaID, exemplo: GrupoID ou ProdutoID.
Um coisa muito legal que o EF CodeFirst faz para nós é criar o banco de dados, mas isto depende do provider do seu banco de dados, nem todos aceitam a criação do banco.
Vamos agora montar um exemplo para carregar dados no nosso banco.
1: using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.Text;
5:
6: namespace EFCodeFirst
7: {
8: class Program
9: {
10: static void Main(string[] args)
11: {
12: var db = new Contexto();
13:
14: db.Database.CreateIfNotExists();
15:
16: var g1 = new Grupo() { Nome = "Peças" };
17: var g2 = new Grupo() { Nome = "Serviços" };
18:
19: db.Grupo.Add(g1);
20: db.Grupo.Add(g2);
21:
22: var p1 = new Produto() { Descricao = "Pneu", Grupo = g1 };
23: var p2 = new Produto() { Descricao = "Roda", Grupo = g1 };
24: var p3 = new Produto() { Descricao = "Alinhamento", Grupo = g2 };
25: var p4 = new Produto() { Descricao = "Balanceamento", Grupo = g2 };
26:
27: db.Produto.Add(p1);
28: db.Produto.Add(p2);
29: db.Produto.Add(p3);
30: db.Produto.Add(p4);
31:
32: db.SaveChanges();
33:
34: var dados = from p in db.Produto
35: select p;
36:
37: foreach (var linha in dados)
38: {
39: Console.WriteLine("{0,-30} - {1}", linha.Grupo.Nome, linha.Descricao);
40: }
41:
42: }
43: }
44: }
O código acima cria o nosso banco de dados no SQL, caso ele não exista (linha 14). Após isto eu inseri os dados em Grupo e Produto, mas percebam que eu simplesmente vinculei os objetos, sem me preocupar com as chaves primárias ou estrangeiras, pois o EF resolve isto para nós desde que seu mapeamento esteja correto.
Assim ao final do código temos o banco de dados criado e os dados inseridos. Veja como ficou o banco de dados no Management Studio.
Veja que o nome do banco de dados é o nome da aplicação mais o nome do Contexto, mas podemos resolver isto adicionando um arquivo App.Config e informando os dados do banco, então vamos adicionar um arquivo de configuração ao nosso exemplo e colocar a seguinte linha.
1: <?xml version="1.0" encoding="utf-8" ?>
2: <configuration>
3: <connectionStrings>
4: <add name ="Contexto" providerName="System.Data.SqlClient" connectionString="data source=(local); initial catalog=ExemploEF; user id=teste; password=teste;"/>
5: </connectionStrings>
6: </configuration>
O nome da string de conexão é o mesmo nome da nossa classe de Contexto. O providerName indica que usamos SQL Server e a string de conexão é padrão de ADO.Net, informando Servidor/Banco de Dados/Usuário.
Executando nosso código novamente o banco chamado EFExemplo será criado e preenchido com os dados.
Visualizando o modelo do CodeFirst
Mas e se você quiser ver como está ficando seu modelo se você está usando somente código ? Para isto existe o Entity Framework PowerTools que permite visualizar o modelo a partir das classes e também gerar um script para o banco de dados. Vejamos como ver o modelo visual do nosso exempo.
Após instalar o PowerTools, clique com o botão direito do mouse sobre a classe Contexto.cs no seu projeto, irá aparecer um menu de contexto EntityFramework, com várias opções.
A primeira opção é justamente a que mostra o modelo gráfico, vamos vê-lo então:
Já tenho um banco de dados e quero usar o CodeFirst
Se você já tiver um banco de dados, o EF PowerTools permite que você faça engenharia reversa e gere o contexto e as classes, para isto clique com o botão direito do mouse em sua Solution no Visual Studio e escolhar Entity Framework no menu.
Esta opção gera todas as classes e relacionamentos do seu modelo, basta informar qual o banco de dados e o servidor na janela abaixo.
Não se esquece de adicionar o EntityFramework CodeFirst com o NuGet antes de fazer a engenharia reversa.
Quando usar Designer ou CodeFirst
Esta é um pergunta bem complicada, eu diria que se você usa somente um banco de dados e precisa trabalhar com Stored Procedures é melhor usar o Designer, principalmenet porquê o CodeFirst ainda não suporta procedures nativamente.
Se você quer criar uma aplicação multibanco, de maneira mais rápida e simples através de classes POCO, então o CodeFirst é sua escolha.
Muito importante saber também que o Entity Framework Designer e o CodeFirst são independentes e podem não compartilhar alguns recursos.