No primeiro post dessa minha série sobre EF 4.1, mostrei um exemplo com três classes POCO, a criação de um Contexto herdado de DbContext para acesso ao banco e um Database Initializer para permitir alguma lógica de inicialização do banco de dados.
No segundos post o mapeamento foi refinado com alguns atributos sobre as classes e suas propriedades, e foram criados alguns formulários para demonstrar operações CRUD, efetuando inserções, edições, e exclusões, utilizando puramente orientação a objeto, sem a necessidade de executar uma única instrução SQL.
Para esse terceiro post, preparei algumas classes adicionais com exemplos de mapeamentos mais complexos e no final vou mostrar um formulário mestre-detalhe.
Voltando ao banco de dados, temos agora a seguinte estrutura:
As três primeiras tabelas já eram conhecidas: Cidades, Estados, Paises.
Foi adicionada uma tabela Pessoa, que faz um relacionamento Um-Para-Um com as tabelas: PessoasJuridicas e PessoasFisicas. Cada pessoa pode ter um ou mais endereços, e para isso foi criada a tabela Enderecos. Cada endereço se relaciona com uma cidade, e possui um tipo de endereço, e então temos a tabela TiposEndereco.
Relacionamento One-To-One (Um-Para-Um)
Para que o EF entenda esse tipo de relacionamento, é necessário que haja em ambos os lados uma propriedade complexa com a palavra reservada virtual. A classe Pessoa ficou assim:
A classe PessoaJuridica contém uma chave própria porém sem o atributo Identity (o valor do Id virá da tabela Pessoa), ou seja, o campo Id é chave primária mas também é chave estrangeira, referenciando o campo Id da tabela Pessoa. Repare na propriedade complexa referenciado a classe Pessoa e no atributo ForeignKey:
A mesma situação ocorre com a classe PessoaFisica, porém nesse caso aproveitei para mostrar como usar a API Fluente do EF, pois em algumas situações não existe todos os atributos necessários, então introduzi uma classe interna para configurar o campo "Sexo" pois quero que no banco de dados o tipo seja char(1) e não varchar(1).
O método Property possui um parâmetro para usar com expressão lambda. Para que essa classe seja utilizada pelo EF, temos que referenciá-la no Contexto, caso contrário, será ignorada. Para fazer isso, devemos sobreescrever o método OnModelCreating e adicionar uma nova instância dessa classe, da seguinte forma:
Nas outras classes adicionadas, não há novidades em relação ao EF, tudo já foi demonstrado neste post e em posts anteriores.
Vou destacar a alteração que fiz na classe MyInitializer, onde cadastrei uma pessoa, uma pessoa física, jurídica, um endereço e um tipo de endereço.
Formulário Mestre-Detalhe (Master-Detail)
Neste formulário, vou apresentar uma listagem com as pessoas que foram cadastradas e seus respectivos endereços:
Para recuperar a lista de pessoas, criei uma lista que contém os dados da pessoa (Id, Nome, Status) da tabela pessoa e na mesma lista adicionei um campo para o Cpf no caso de a pessoa ser pessoa física e o Cnpj no caso de a pessoa ser jurídica. Pela maneira que modelei esse banco de dados, a mesma pessoa pode ser tanto física quanto jurídica. Normalmente eu faria um classe específica chamada PessoaEnderecoModel, somente para exibir essas informações, mas desta vez fiz diferente, criei um tipo anônimo, converti para um List<T> e preenchi os dados ao percorrer os resultados da consulta. Ficou da seguinte forma:
E finalmente, para exibir os endereços da pessoa que foi selecionada na lista, eu pego o Id da pessoa que foi selecionada através do valor da célula do GridViewMaster, e faço uma consulta filtrando os endereços usando a cláusula Where. Deixei comentada as duas formas de utilizar o EF com LINQ. Use a forma de sua preferência, o resultado será o mesmo!
Próximo artigo vou falar um pouco sobre validação, em seguida mostrarei uma classe base para ser usada no padrão repositório e falarei mais sobre o DbContext e utilizar o padrão UnitOfWork. Tem assunto ainda pra mais uns dez posts!
[]'s
Comentário de Hugo Campos em 4 julho 2011 às 9:56 Bom dia Jone,
Será que você poderia me dar uma ajuda nisso.
var EnderecoComercial = new TipoEndereco { Descricao = "Comercial" };
var EnderecoResidencial = new TipoEndereco { Descricao = "Residencial" };
ctx.TiposEndereco.Add(EnderecoComercial);
ctx.TiposEndereco.Add(EnderecoResidencial);
teria alguma outra forma de fazer isso?
Dessa forma que vocë fez está correta, mas tem ainda uma maneira mais direta ainda:
ctx.TiposEndereco.Add(new TipoEndereco { Descricao = "Comercial"});
ctx.TiposEndereco.Add(new TipoEndereco { Descricao = "Residencial"});
ctx.SaveChanges();
Comentário de Thiago Lagos em 21 dezembro 2011 às 6:00 Primeiramente gostaria de parabenizar pelo excelente trabalho!
Gostaria de saber se poderia nos mostrar como ficaria esta estrutura com MySql ao invés de SQLExpress.
Comentário de Reuber Junior em 8 maio 2012 às 20:36 Olá Jone, muito obrigado por compartilhar estes post´s
Tenho uma estrutura parecida com o cadastro de pessoas ( pessoas - pessoas juridicas - pessoas fisicas).
Como faço para que quando eu excluir uma pessoa, a exclusão se propague para as tabelas filhas? Exclusão em cascata? Com uma estrutura parecida, quando o Entity Framework cria o banco, ele não "adiciona" a opção de deleção em cascata nas tabelas filhas. Poderia me ajudar?
Comentário de Marcos Bazilio em 15 junho 2012 às 16:40 Parabéns pelo Post, caso você possa me ajudar, estou com a seguinte dúvida, tenho que fazer um CRUD onde em tal cadastro tenho trabalhar com três tabelas relacionadas, fornecedor, fone, cidade, tenho que ter um DropDowList da tabela cidade, e no Web Form tenho que conseguir gravar vários telefones para o mesmo fornecedor.
Obrigado
Comentar
21 maio 2013 de 8:30 a 12:00 – SEBRAE
O Delphi e a suíte RAD Studio são as plataformas para o desenvolvimento de aplicações multidispositivo verdadeiramente nativas. E são ideais para você, que precisa desenvolver – rapidamente! - aplica…
Organizado por Adriano Israel Antunes | Tipo: tour, delphi, multidevice
1 Comentar 0 Curtiram isto© 2013 Criado por Gustavo Malheiros.
Você precisa ser um membro de PantaNet para adicionar comentários!
Entrar em PantaNet