Foreign key e Independent Associations no Entity Framework (pt-BR)
*Dica: Assine o RSS feed ou **e-mail *para esta página Wiki para obter notificação automática quando ela for atualizada!
Introdução
Neste artigo é apresentada a utilização do uso das associações por Foreign Key (Chave Estrangeira) e Independent Associations (Associação independente), demonstrado através de exemplo prático.
Nas primeiras versões do Entity Framework só era possível fazer um único tipo de associação entre as entidades, a Independet Associations, esta primeira abordagem de relacionamento entre as entidades era totalmente orientada a objeto, onde a relação entre dois ou mais objetos é feita através de referencias.
Exemplo de Independent Associations ** **
Por exemplo, um objeto Produto que possui dentro dele (associação) outro objeto Categoria.
public class Produto
{
public int Id { get; set; }
public string Descricao { get; set; }
public Categoria Categoria { get; set; }
}
O problema deste tipo de associação é que o Entity Framework torna, por vezes, muito complexa a sua implementação, seguindo o raciocínio do exemplo do Produto acima, para adicionar um novo produto, é preciso fazer uma busca nas categorias, achar um objeto categoria e associar ele (com todas as suas dependências/propriedades, no caso a propriedade UnidadeDeMedida) a este produto. E esta complexidade tende a aumentar em objetos muito complexos, que possuam vários outros objetos dentro.
class Program
{
static void Main()
{
var meucontexto = new MeuContexto();
var produto = new Produto();
produto.Descricao = "Arroz";
produto.Categoria = meucontexto.Categorias.Include("UnidadeDeMedida").ToList().FirstOrDefault();
meucontexto.Produtos.Add(produto);
meucontexto.SaveChanges();
}
}
Observe, que foi solicitado ao Entity Framework para incluir na sua busca, a UnidadeDeMedida, que é uma associação que existe entre as Classes Categoria e UnidadeDeMedida, como é demonstrado abaixo.
public class Categoria
{
public int Id { get; set; }
public string Nome { get; set; }
public UnidadeDeMedida UnidadeDeMedida { get; set; }
}
public class UnidadeDeMedida
{
public int Id { get; set; }
public string Descricao { get; set; }
public string Abreviacao { get; set; }
}
Logo, se tenho uma classe que possui varias associações, é necessário trazer todas estas associações “secundárias” para realizar uma simples associação entre Produto e Categoria.
Já no Entity Framework 4 ou superior, o time de desenvolvimento do Entity Framework incluiu um novo tipo de associação onde o modelo conceitual inclui a propriedade do tipo Foreign Key, para definir as associações entre as entidades.
Exemplo de Associação por Foreign Key
Voltando ao nosso exemplo do Produto, agora ao invés de somente ter uma propriedade do tipo Categoria, o objeto Produto teria outra propriedade do tipo int, por convenção, o nome da propriedade Foreign Key é o nome da Propriedade Complexa associada, seguida pelo sufixo Id (no caso CategoriaId), que seria usada como Foreign Key (chave estrangeira), e nesta abordagem, na hora de cadastrar um novo produto, bastaria passar o Id da Categoria, para essa propriedade do tipo int, e a associação estaria feita, o Entity Framework se encarregaria do resto.
class Program
{
static void Main()
{
var meucontexto = new MeuContexto();
var produto = new Produto();
produto.Descricao = "Arroz";
produto.CategoriaId = meucontexto.Categorias.ToList().FirstOrDefault().Id;
meucontexto.Produtos.Add(produto);
meucontexto.SaveChanges();
}
}
public class Produto
{
public int Id { get; set; }
public string Descricao { get; set; }
public int CategoriaId { get; set; }
public Categoria Categoria { get; set; }
}
Repare que neste exemplo, não é mais necessário a inclusão da UnidadeDeMedida, que esta associada a categoria, para que se possa criar uma associação entre Produto e Categoria.
Considerações
Este artigo não tem o propósito de debater os meandros desta abordagem se ela é boa ou não, se quebra ou não as regras da orientação objeto, uma vez que se tem a Foreign Key para fazer associação entre objetos, o próprio time de desenvolvedores do Entity Framework escreveu um artigo sobre isso, que diz que essa decisão deve ser tomada pelo desenvolvedor.
Verdade seja dita, o uso de Foreign Key diminui bastante a complexidade do código, o que torna muito mais fácil a manutenção futura, uma vez que não é preciso trazer todo o emaranhado de objetos complexo associadas a uma entidade, para fazer uma simples associação entre esses objetos, sem levar em conta o desempenho nas consultas realizadas para essas associações.
Exemplo completo
using System;
using System.Data.Entity;
using System.Linq;
namespace ChaveEstrangeira
{
class Program
{
static void Main()
{
var meucontexto = new MeuContexto();
var categoria = new Categoria();
categoria.Nome = "Alimentos";
categoria.UnidadeDeMedida = new UnidadeDeMedida
{
Abreviacao = "PCT",
Descricao = "Pacote"
};
meucontexto.Categorias.Add(categoria);
meucontexto.SaveChanges();
var produto = new Produto();
produto.Descricao = "Arroz";
produto.CategoriaId = meucontexto.Categorias.ToList().FirstOrDefault().Id;
//produto.CategoriaId = 1; //Caso saiba o id, basta passar somente o Id.
meucontexto.Produtos.Add(produto);
meucontexto.SaveChanges();
//Busca no contexto o produto cadastrado
var produtoRetornado = meucontexto.Produtos.Include("Categoria").ToList().FirstOrDefault();
Console.WriteLine(produtoRetornado.Categoria.Nome);
}
}
public class Produto
{
public int Id { get; set; }
public string Descricao { get; set; }
public int CategoriaId { get; set; }
public Categoria Categoria { get; set; }
}
public class Categoria
{
public int Id { get; set; }
public string Nome { get; set; }
public int UnidadeDeMedidaId { get; set; }
public UnidadeDeMedida UnidadeDeMedida { get; set; }
}
public class UnidadeDeMedida
{
public int Id { get; set; }
public string Descricao { get; set; }
public string Abreviacao { get; set; }
}
public class MeuContexto : DbContext
{
public DbSet<Produto> Produtos { get; set; }
public DbSet<Categoria> Categorias { get; set; }
}
}
Artigos RelacionadosForeign Keys in the Entity Framework
Cleyton Ferrari
Twitter: @cleytonferrari
TI Selvagem - Users Group Leader
http://www.tiselvagem.com.br