Entity Framework
- Definindo um modelo com herança Table Per Type
Este série de artigos é dedicada ao Entity Framework e tem o objetivo de dar uma introdução básica e uma visão geral de como usar este importante recurso da plataforma .NET. Os artigos são parcialmente baseados na documentação da MSDN de onde são citadas as respectivas referências.
Iniciando com o Entity Framework
Conceito
A ADO .NET Entity Framework foi projetado para permitir que a criação de aplicações com acesso a dados use o modelo de programação feito contra um modelo conceitual ao invés do antigo modelo de programação feito diretamente contra um banco de dados relacional. O objetivo é diminuir a quantidade de código e o tempo de manutenção necessária exigida nestas aplicações orientada a dados.
A ADO .NET Entity Framework é uma framework que abstrai o esquema de um banco de dados relacional e o apresenta como um modelo conceitual. Abaixo a figura que representa a arquitetura em camadas do Entity Framework: (Até o lançamento do VS 2010, previsto para o primeiro trimestre.)
![]() |
Data Source
: Representa a base da arquitetura onde estão armazenados os dados;
Data Providers : Os dados são acessados por um ADO.NET data provider. Até o momento tanto o SQL Server como o MySQL são suportados e provavelmente em breve os principais RDBMS do mercado (Oracle, MySQL, DB2, Firebird, Sybase, VistaDB, SQLite, ...) terão um provider para o EF. Entity Data Model (EDM) : O Entity Data Model é constituído de 3 partes:
Entity Client : O EntityClient é um provedor gerenciado ADO.NET que suporta o acesso a dados descritos no EDM. Ele é similar ao SQLClient, e fornece diversos componentes como EntityCommand, EntityConnection e EntityTransaction; Object Services : Este componente permite realizar consultas, atualizações, inclusões e exclusões nos dados, expressados como objetos CLR fortemente tipados que são instâncias de entity types. Ele da suporte tanto a consultas Entity SQL como LINQ to Entities; Entity SQL (ESQL) : É uma derivação da Transact-SQL, projetada para consultar e manipular entidades definidas no EDM. Ele dá suporte herança e associação sendo que tanto os componentes Object Services como os componentes Entity Client podem executar instruções Entity SQL; LINQ to Entities : É
uma linguagem de consulta fortemente tipada para consultar entidades
definidas no EDM; |
Criar, modificar e deletar objetos e aplicar estas alterações ao banco de dados é muito fácil com o Entity Framework. Através do Object Services que gerencia todas as alterações feitas nos objetos e gera e executa as instruções T-SQL que irão realizar as operações de inclusão, alteração e exclusão contra a fonte de dados. Tudo isso é feito através da chamada do método SaveChanges do ObjectContext (equivalente ao SubmitChanges do LINQ to SQL).
Quando usamos uma ferramenta OR/M como o Entity Framework desejamos definir da melhor forma possível o nosso modelo de entidades de forma a que tenhamos um bom desempenho e que o esforço necessário para tratar o modelo seja o mínimo possível. Como todos já sabem o modelo relacional de banco de dados não se ajusta adequadamente ao paradigma da orientação a objetos e uma ferramenta OR/M que se preze deve oferecer recursos para tornar a discrepância entre esses dois mundos o menos traumática possível.
Na programação orientada a objetos quando um objeto é um tipo de outro objeto podemos usar a herança para compartilhar suas propriedades de forma que as propriedades da classe base são expostas diretamente para o tipo derivado.
A herança é um recurso da orientação objeto que não existe nativamente no mundo relacional e uma ferramenta OR/M deve oferecer recursos para que possamos implementar a herança em nosso modelo de entidades de forma a obter um melhor rendimento. Felizmente o Entity Framework oferece esses recursos.
Nota: No paradigma da orientação a objetos a herança é muitas vezes usada para representar que apresentam uma relacionamento do tipo É-um. Ou seja quando um objeto é uma especificação do outro objeto.
O Entity Framework suporta 3 modelos diferentes de herança:
O modelo Table-per-Type é uma forma de modelar a herança onde cada entidade é mapeada para uma tabela diferente na camada de armazenamento. Cada tabela contém todas as propriedades para a entidade bem como uma chave que mapeia em última instância a tabela raiz/entidade.
A herança do tipo Table per Type (TPT) define uma herança que é descrita no banco de dados com tabelas separadas onde uma tabela fornece detalhes adicionais que descrevem um novo tipo baseado em outra tabela. Este cenário é mais comum do que se imagina e pode ser visto na figura abaixo que exibe duas tabelas onde podemos aplicar a herança TPT.
| Vejamos um modelo bem simples
onde podemos usar a herança TPT: A figura ao lado mostra o relacionamento entre a tabela Contato e Clientes. Onde um contato pode ter uma entidade cliente relacionada.
|
![]() |
Vamos mostrar um exemplo prático definindo um modelo conceitual do tipo Table Per Type (TPT) para isso eu vou criar um modelo de dados bem simples usando o Microsoft SQL Server 2008 Express e o SQL Server 2008 Management Studio Express Edition.
Abaixo temos as tabelas : Pessoa, Supervisor, Professor , Aluno e Estagiário.
![]() |
Nosso objetivo é implementar o modelo conceitual da herança Table Per Type suportada no EDM de forma que possamos ter acesso as informações compartilhadas entre as tabelas. |
Eu não vou entrar no mérito do modelo de dados pois ele esta sendo usado apenas para ilustrar a implementação da herança TPT no Entity Framework.
Nota: Pegue o script para gerar as tabelas aqui : Escola.sql
Neste caso estamos modelando uma hierarquia de herança onde temos a entidade base Pessoa e 3 entidades que herdam de Pessoa :: Aluno, Supervisor e Professor. Além disso temos a entidade Estagiario que herda da entidade Aluno.
Implementando o modelo da herança Table Per Type no Entity Framework
Vamos usar o Visual Studio 2008 e criar um projeto do tipo Windows Forms Application com o nome EF_herancaTPT;
A seguir no menu Project selecione Add New Item e escolha o template ADO .NET Entity Data Model, informe o nome Escola.edmx e clique Add;
![]() |
A seguir selecione a opção Generate From dataBase e clique no botão Next>;
A seguir selecione a conexão com o banco de dados Escola e clique em OK;
![]() |
A seguir aceite os valores padrões informados para a connection String e clique no botão Next>;
![]() |
Na janela seguinte selecione as tabelas criadas , aceite o nome padrão para o namespace e clique em Finish;
![]() |
Como resultado final será exibida o modelo de entidades criados no descritor do Entity Framework. O nosso EDM:
![]() |
Pois é agora que o nosso trabalho vai começar.![]()
Vamos começar alterando os nomes das entidades alterando o nome da propriedade Entity Set Name para o plural em todas as entidades. Veja abaixo a janela de propriedades para a entidade Pessoa:
![]() |
Da mesma forma altere a
propriedade Entrity Set Name das demais entidades para:
|
A seguir vamos excluir todas as associações geradas no EDM selecionando cada uma delas e pressionando a tecla Delete. Na figura abaixo vemos as associações selecionadas e em seguida excluídas:
![]() |
![]() |
A seguir selecione a entidade Pessoa e clique com o botão direito do mouse selecionando Add -> Inheritance;
Será apresentada a janela Add Inheritance onde iremos selecionar a entidade base - Pessoa e a derivada Aluno clicando em OK;
![]() |
![]() |
Repita o procedimento acima incluindo a herança para as entidades derivadas Professor e Supervisor;
Finalmente selecione a entidade Aluno e clique com o botão direito e selecione Add -> Inheritance e na janela Add Inheritance selecione a entidade base Aluno e a entidade derivada Estagiario;
A final deveremos ter o seguinte modelo no descritor do EF:
![]() |
A seguir vamos excluir as propriedades AlunoID, estagiarioID, supervisorID e professorID das entidades pois será herdada a propriedade pessoaID;
Para excluir essas propriedades selecione-as, clique com o botão direito do mouse, e selecione a opção Delete;
![]() |
Como excluímos essas propriedades das entidades derivadas, a coluna pessoaID da tabela correspondente não esta mais mapeada. Precisamos então refazer o mapeamento para que a propriedade pessoaID seja herdada. Vamos lá...
Selecione cada uma das entidades derivadas e na janela Mapping Details mapeie cada coluna para a coluna pessoaID conforme a figura abaixo mostra para a entidade Supervisor:
![]() |
Faça este processo para cada entidade derivada incluindo entidade Estagiario.
Pronto. Com isso terminamos de criar o nosso modelo conceitual baseado na herança TPT.
Vamos testar...![]()
Vamos definir no formulário form1.vb, criado por padrão, uma interface bem simples apenas para mostrar que temos acesso as propriedades herdadas pelas entidades derivadas da entidade base.
Nota: Eu poderia ter criado uma aplicação console, seria mais simples ainda mas preferi criar uma aplicação Windows Aplication.
No formulário form1.vb inclua os seguintes controles : 5 Labels, 5 ListBox e 5 Button conforme o leiaute da figura abaixo:
![]() |
Vamos iniciar exibindo a entidade Pessoa e para isso vamos incluir o código abaixo no evento Click do botão Exibir Pessoas:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Using escola As New EscolaEntities1
Dim pessoa = From p In escola.Pessoa _
Select p
For Each p As Pessoa In pessoa
lstPessoa.Items.Add(p.nome & "-" & p.email)
Next
End Using
End Sub
|
Neste código definimos a variável escola como uma instância do nosso Contexto (ObjectContext) e em seguida efetuamos uma consulta retornando os objetos da entidade Pessoa.
Para exibir as propriedades da entidade percorremos a entidade usando um laço For/Each.
Vamos agora exibir a entidade Professor. Para acessar as propriedades herdadas das entidades derivadas incluímos o código a seguir no evento Click do botão : Exibir Professores:
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Using escola As New EscolaEntities1
Dim pessoa = From p In escola.Pessoa.OfType(Of Professor)() _
Select p
For Each p In pessoa
lstProfessor.Items.Add(p.nome & "-" & p.email & "=>" & p.salario)
Next
End Using
End Sub
|
Neste código usamos o recurso da herança criada no modelo Table Per Type onde selecionamos as propriedades do tipo derivado Professor:
Dim pessoa = From p In
escola.Pessoa.OfType(Of
Professor)() _
Select p
Observe que após feito este procedimento temos acesso as propriedades herdadas : nome e email e da propriedade salario da entidade Professor.
For Each p In pessoa
lstProfessor.Items.Add(p.nome & "-" & p.email & "=>" & p.salario)
Next
Para exibir as propriedades para as demais entidades o procedimento é o mesmo mudando apenas o nome do tipo e da propriedade que desejamos acessar. Veja abaixo o código referente aos demais botões (todos no evento Click):
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
Using escola As New EscolaEntities1
Dim pessoa = From p In escola.Pessoa.OfType(Of Supervisor)() _
Select p
For Each p In pessoa
lstSupervisor.Items.Add(p.nome & "-" & p.email & "=>" & p.turno)
Next
End Using
End Sub
|
| Entidade Supervisor |
Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
Using escola As New EscolaEntities1
Dim pessoa = From p In escola.Pessoa.OfType(Of Aluno)() _
Select p
For Each p In pessoa
lstAluno.Items.Add(p.nome & "-" & p.email & "=>" & p.nota & "," & p.curso)
Next
End Using
End Sub
|
| Entidade Aluno |
Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click
Using escola As New EscolaEntities1
Dim pessoa = From p In escola.Pessoa.OfType(Of Estagiario)() _
Select p
For Each p In pessoa
lstEstagiario.Items.Add(p.nome & "-" & p.email & "=>" & p.curso & "," & p.creditos)
Next
End Using
End Sub
|
| Entidade Estagiario |
O resultado obtido pode ser visto na figura abaixo :
![]() |
Uma outra forma de obter o mesmo resultado seria usar o código exibido a seguir que coloquei no evento Click do botão - Exibir Todos :
Private Sub Button6_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button6.Click
Using escola As New EscolaEntities1
Dim pessoa = From p In escola.Pessoa _
Select p
For Each p As Pessoa In pessoa
lstPessoa.Items.Add(p.nome & "-" & p.email)
Next
For Each tp In pessoa If TypeOf tp Is Professor Then
Dim p As Professor = DirectCast(tp, Professor)
lstProfessor.Items.Add(tp.nome & "-" & tp.email & "=>" & p.salario)
End If
If TypeOf tp Is Supervisor Then
Dim s As Supervisor = DirectCast(tp, Supervisor)
lstSupervisor.Items.Add(tp.nome & "-" & tp.email & "=>" & s.turno)
End If
If TypeOf tp Is Aluno Then
Dim a As Aluno = DirectCast(tp, Aluno)
lstAluno.Items.Add(tp.nome & "-" & tp.email & "=>" & a.nota & "," & a.curso)
End If
If TypeOf tp Is Estagiario Then
Dim est As Estagiario = DirectCast(tp, Estagiario)
lstEstagiario.Items.Add(tp.nome & "-" & tp.email & "=>" & est.creditos)
End If
Next
End Using
End Sub
|
Neste código verificamos o tipo de cada entidade e após realizar o casting para o tipo desejado exibimos as propriedades herdades e as específicas:
Nota : Para saber mais sobre Casting no VB .NET veja o meu artigo: VB.NET - Casting
Pegue o projeto completo aqui:
EF_HerancaTPT.zip
Dessa forma mostramos um exemplo básico de como implementar a herança TPT no Entity Framework .
Aguarde em breve novos artigos sobre este assunto...
Eu sei é apenas Entity Framework
mas eu
gosto...![]()
Referências:
José Carlos Macoratti