Entity Framework - Conceitos básicos - Dando uma espiada no modelo conceitual


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)

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:

  • Conceptual schema definition language (CSDL) : Declara e define entidades, associações, herança, etc,. As Entity classes são geradas a partir deste esquema;
  • Store schema definition language (SSDL) : Metadados que descreve o container de armazenamento (=banco de dados) que persiste os dados;
  • Mapping specification language (MSL) : Mapeia as entidades no arquivo CSDL para tabelas descritas no arquivo SSDL;

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;
 

Se você estava acostumado com o LINQ to SQL e passou a usar o pensa em usar o Entity Framework poderá a primeira vista se deparar com algumas diferenças básicas que precisa entender para não se confundir. Senão vejamos...

Tanto o LINQ to SQL como o Entity Framework efetuam o mapeamento objeto relacional da mesma forma certo ? Não errado.

Vamos fazer uma comparação de um  modelo ORM gerado a partir do banco de dados Northwind.mdf  usando os dois recursos e vamos comparar.

Para ficar mais simples não vou usar todas as tabelas do banco de dados Northwind.mdf irei apenas focar nas tabelas Employees, EmployeesTerritories e Territories.

Vamos criar uma aplicação do tipo WIndows Forms Application usando o Visual Studio 2008 com SP1 com o nome ORM_Demo;

A seguir vamos abrir uma conexão com o banco de dados Northwind.mdf usando o Server Explorer;

Agora para começar crie um DataBase Diagram usando as tabelas Employees, EmployeesTerritories e Territories. Veja abaixo o resultado:
 

Pois bem agora a partir do menu Project -> Add New Item selecione o template LINQ to SQL Classes aceitando o nome padrão.

A seguir arraste e solte a partir do Server Explorer as tabelas Employees, EmployeesTerritories e Territories para o descritor. Veja o resultado abaixo:
 

Note que para cada tabela foi gerada uma entidade e o relacionamento foi representado pela associação entre as entidades.

Vamos agora gerar um Entity Data Model. A partir do menu Project -> Add New Item selecione o template ADO .NET Entity Data Model e informe o nome Entidades.edmx e clique em Add;

Seguindo o assistente selecione a opção Generate from Database e clique em Next> ;

Aceite as informações para a conexão e clique em Next>;

Selecione as tabelas Employees, EmployeesTerritories e Territories e clique em Finish. O resultado obtido será o seguinte:
 

Nota: Dependendo da sua versão o resultado poderá ser um pouco diferente.

Percebeu a diferença ???

A primeira diferença é que não existe a entidade EmployeeTerritories (a tabela de junção) em seu lugar existe a Navigation Properties que permite o acesso correspondente a territórios e empregados e como existe um relacionamento da tabela Employees com ela mesma existem duas Navigation Properties: Employees1 e Employees2 que são responsáveis pelos relacionamentos.

Nota: A tabela de junção não foi incluída no modelo gerado pois continha somente as chaves primárias e nenhuma coluna adicional. Para outros casos onde isto não é verdade veja o artigo :Entity Framework -  O mapeamento Muitos-Para-Muitos

Outra ponto importante a ser destacado: não existe chave estrangeira (foreign key) elas foram substituídas pela Navigation Properties.

Dessa forma o Entity Framework permite que tratemos com objetos que representam entidades na vida real e não apenas objetos que refletem tabelas como o LINQ To SQL.

Para o exemplo deste artigo abra o formulário form1.vb e inclua um controle ListBox e dois controles Button conforme o leiaute abaixo:
 

Agora vamos realizar duas consultas para ilustrar o acesso as entidades em um relacionamento muitos-muitos deste tipo:

No evento click do botão - Exibir Employees -> Territories , coloque o código abaixo:
 
 Private Sub btnExibirEmployeesTerritories_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExibirEmployeesTerritories.Click
        Using db As New NorthwindEntities
            Dim consultaEmployees = From emp In db.Employees From t In emp.Territories _
                                                             Select emp.FirstName, t.TerritoryDescription
            For Each emp In consultaEmployees.OrderBy(Function(x) x.FirstName)
                lstDados.Items.Add(emp.FirstName & " => " & emp.TerritoryDescription)
            Next
        End Using
    End Sub

 

O resultado obtido é exibido na figura a seguir:
 

No evento click do botão - Exibir Territories  -> Employees, coloque o código abaixo:
 
Private Sub btnExibirTerritoriesEmployees_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExibirTerritoriesEmployees.Click
        Using db As New NorthwindEntities
            Dim consultaTerritories = From t In db.Territories From emp In t.Employees _
                                                           Select t.TerritoryDescription, emp.FirstName
            For Each tr In consultaTerritories.OrderBy(Function(x) x.TerritoryDescription)
                  lstDados.Items.Add(tr.TerritoryDescription & " => " & tr.FirstName)
            Next
        End Using
    End Sub

O resultado é mostrado na figura abaixo:
 

É claro que podemos efetuar outras formas de consultas para ilustrar vou mostrar mais duas consultas e para isso eu vou incluir mais dois botões de comando no formulário.

A primeira consulta exibe o primeiro nome do empregado e seu respectivo território:
 
Private Sub btnExibirEmployeesTerritories2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExibirEmployeesTerritories2.Click
        Using db As New NorthwindEntities
            Dim consulta = (From emp In db.Employees.Include("Territories") _
                            Select emp)
            For Each emp In consulta
                lstDados.Items.Add(emp.FirstName)
                For Each t In emp.Territories
                    lstDados.Items.Add("    => " & t.TerritoryDescription)
                Next
            Next
        End Using
    End Sub

Resultado obtido:

A segunda consulta exibe o nome do território e o respectivo empregado:
 
Private Sub btnExibirTerritoriesEmployees2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExibirTerritoriesEmployees2.Click
        Using db As New NorthwindEntities
            Dim consulta = (From t In db.Territories.Include("Employees") _
                            Select t)
            For Each t In consulta
                lstDados.Items.Add(t.TerritoryDescription)
                For Each emp In t.Employees
                    lstDados.Items.Add("    => " & emp.FirstName)
                Next
            Next
        End Using
End Sub

Resultado:

É importante que você compreenda os conceitos envolvidos pois eles serão usados de forma implícita pelo Entity Framework.

Pegue o projeto aqui : EF_mpm.zip

Eu sei é apenas Entity Framework mas  eu gosto...

Referências:


José Carlos Macoratti