Entity Framework - Gerenciando Objetos (Code-First/VB.NET)



Este artigo faz uma revisão dos conceitos básicos do gerenciamento de objetos através do Entity Framework e mostra como é simples usar o Code-First na linguagem VB .NET.

O Entity Framework é uma extensão ao ADO .NET que é a tecnologia de acesso a dados da Microsoft que você usa para fazer a conexão e o tratamento das informações de um banco de dados específico.

O Entity Framework(EF) estende a ADO .NET abstraindo os comandos da ADO .NET pois com o EF você não vai programar para o banco de dados vai programar para objetos que foram mapeados a partir do seu modelo pelo EF. Portanto você não terá que utilizar nenhum dos objetos da ADO .NET como DataAdapter, DataReader, DataSet, DataTable, etc. nem comandos SQL como SELECT/INSERT/UPDATE quem vai fazer isso para você será o EF.

O EF permite que isso ocorra fazendo a abstração do modelo do banco de dados e realizando o mapeamento objeto relacional entre o modelo conceitual de objetos e o modelo físico que é o banco de dados.

O EF já esta integrado ao Visual Studio 2010 e às versões Express (VB.NET e C#) e portanto você não tem que instalar nada para usar o Entity Framework apenas o provider do banco de dados que você deseja usar.

Na figura abaixo temos um esquema básico do funcionamento do EF:

Além de simplificar a codificação reduzindo a quantidade de código que você tem que produzir o EF  permite a utilização do recurso Intellisense o que torna ainda mais produtivo a sua utilização e evita que você cometa erros de sintaxe ou tenha que se lembrar de nomes de recursos(nome da tabela, campo,etc.)

O EF utiliza o ADO .NET Data Provider que é suportado pela maioria dos principais SGBD do mercado como  SQL Server, Oracle, MySQL, FireBird , etc.

Veja a relação de providers disponíveis em : http://msdn.microsoft.com/en-us/data/dd363565.aspx

Para conhecer os .NET Framework Data Providers (ADO.NET) veja este link:
http://msdn.microsoft.com/en-us/library/a6cd7c08.aspx

A partir da Versão 4.1 do Entity Framework temos a abordagem Code First e a nova API DbContext. Esta API fornece uma interface mais produtiva para trabalhar com o Entity Framework e pode ser usada com o seguintes padrões de desenvolvimento:

As classes POCO -  POCO-Plain Old CLR Object - são classes simples de domínio que possuem apenas get/sets e um construtor e que não dependem de nenhum framework; as classes POCO não são obrigadas a herdar de nenhuma outra classe ou implementar nenhuma interface. Portanto as classes POCO são independente de frameworks.

A API DbContext nada mais é do que uma abstração simplificada do ObjectContext e diversos outros tipos introduzidos nas versões anteriores do Entity Framework. Esta API é otimizada para realizar as tarefas mais comuns e dar suporte a padrões de código como "Unit Of Work Pattern" e  "Repository Pattern". A API DbContext é um invólucro para ObjectContext e além disso contém:  Um conjunto de APIs que são mais fáceis de usar do que a exposta pelo ObjectContext e APIs que permitem utilizar o recurso do Code-First e as convenções;

Obs: Para que você se familiarize com os conceitos básicos do Entity Framework veja os artigos da seção Entity Framework do site Macoratti.net. Boa parte dos conceitos já abordados em outros artigos são repetidos aqui.

O recurso Code First do EF permite que você crie primeiro as classes POCO que a partir delas o seu banco de dados seja gerado de forma automática. Ele faz isso usando um container que chamamos de Contexto e que faz o mapeamento das classes criadas com o banco de dados e que usando convenções (que podemos controlar) gera o banco de dados e as tabelas através desse mapeamento.

Quando decidimos usar o Code-First não precisamos começar nossa aplicação criando o banco de dados ou definindo um esquema mas podemos iniciar escrevendo classes .NET para definir o modelo de objetos do nosso domínio sem ter que misturar a lógica de persistência de dados com as classes.

Podemos usar Code First e apontar para um banco de dados existente ao invés de criar o banco de dados.(Este padrão é conhecido como DataBase First) A maneira mais fácil de de usar o Code First com um banco de dados existente é adicionar uma string de conexão ao arquivo App.Config ou arquivo Web.Config (para aplicações ASP .NET) que tenha o mesmo nome do seu DbContext derivado.
Exemplo:

<connectionStrings>
   <add   name="
MeuContexto"  providerName="System.Data.SqlClient" connectionString="Server=.\SQLEXPRESS;Database=Produtos;Trusted_Connection=true;" />
</connectionStrings>

Neste artigo eu vou utilizar o Visual Basic 2010 Express Edition e mostrar como podemos usar o Entity Framework e o recurso Code First para criar o banco de dados e a tabela a partir da definição da classe POCO. Vou mostrar também como podemos gerenciar os objetos gerados pelo mapeamento para tratarmos as informações do banco de dados.

Abra o Visual Basic 2010 Express Edition e crie um novo projeto do tipo Windows Forms Application com o nome GerenciandoObjetos_EF;

Com a solução criada vamos incluir nossa primeira classe POCO no projeto que irá representar uma tabela do banco de dados.

No menu Project clique em Add Class e informe o nome Cliente.vb;

A seguir inclua o seguinte código nesta classe:

Imports System.ComponentModel.DataAnnotations
Imports System.ComponentModel.DataAnnotations.Schema

<Table("Clientes")>
Public Class Cliente

    <Key()>
    Public Property Id As Integer
    Public Property nome As String
    Public Property email As String

End Class

Observe que definimos uma classe chamada Cliente com três propriedades : Id, nome e email

Essa classe será mapeada pelo EF através do contexto que iremos criar em seguida para gerar a tabela Cliente no banco de dados da aplicação que também será criado pelo EF.

Vamos agora definir a classe para o nosso contexto. Essa classe deverá herdar de DbContext e deverá definir uma propriedade do tipo DbSet().

O EF Code First permite que você conecte facilmente suas classes POCO do modelo em um banco de dados através da criação de uma classe "DbContext" que expõe propriedades públicas que mapeiam para tabelas do banco de dados.

No menu Project clique em Add Class e informe o nome Contexto.vb;

Imports System.Data.Entity

Public Class ClientesDB
    Inherits DbContext

    Public Property Clientes() As DbSet(Of Cliente)

End Class

Vejam como é simples. Definindo apenas essas duas classes já podemos partir para o gerenciamento dos objetos através do código usando o EF.

No formulário form1.vb que vamos definir uma interface bem simples pois nosso objetivo é mostrar como podemos usar o EF para gerenciar os objetos realizando as operações de consulta, alteração, exclusão e inclusão.

Inclua a partir da Toolbox no formulário form1.vb os seguintes controles:

Conforme o leiaute da figura abaixo:

Agora vamos definir o código usando o evento Click de cada um dos botões de comando:

1- Botão de comando Incluir:

    Private Sub btnIncluirObjeto_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles 
btnIncluirObjeto.Click
        Dim db As New ClientesDB
        Dim cli As New Cliente() With
        { _
         .nome = "Macoratti", _
         .email = "macoratti@yahoo.com" _
        }
        'Use (ObjectSet <TEntity> .AddObject())
        'Use (ObjectContext.AddObject())
        'Use (EntityCollection <TEntity> .Add())
        db.Clientes.Add(cli)
        db.SaveChanges()
        ConsultaObjetos(db)
    End Sub

A primeira coisa que devemos fazer é criar uma instância do nosso contexto : Dim db As New ClientesDB

A seguir criamos uma instância da classe Cliente e atribuímos os valores para as propriedades nome e email;

Para adicionar novos objetos ao conjunto de entidades(Entity Set), você deve criar uma instância de um Entity Type e adicionar o objeto para o object context.Os Objetos ligados ao contexto do objeto são gerenciados por esse contexto de objeto.

Você pode adicionar novos objetos a um object context usando um dos seguintes métodos:

1- O método AddObject no ObjectSet.
2- O método AddObject em ObjectContext.
3- O método Add no EntityCollection.


Para entidades Entity Framework geradas e objetos proxy POCO, as entidades adicionadas estão ligados ao contexto em que o objeto principal está ligado. Entidades POCO estão ligadas quando o método DetectChanges for chamado.

As seguintes considerações se aplicam quando da inclusão de objetos:

2- Rotina ConsultaObjetos

 Private Sub ConsultaObjetos(ByVal _db As ClientesDB)
        lstObjetos.Items.Clear()
        Dim clientes = _db.Clientes
        For Each c In clientes
            lstObjetos.Items.Add(c.Id & "-" & c.nome & "-" & c.email)
        Next
    End Sub

Esta rotina recebe uma instância do contexto criado e exibe no controle ListBox os valores para as propriedades id, nome e email do objeto.

3- Botão de comando Alterar:

 Private Sub bntAlterarObjeto_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles 
bntAlterarObjeto.Click
        Dim db As New ClientesDB
        Dim c As Cliente = db.Clientes.First(Function(i) i.Id = 1)
        c.email = "macoratti@ig.com.br"
        db.SaveChanges()
        ConsultaObjetos(db)
    End Sub

Quando qualquer propriedade escalar ou complexa de um objeto é alterada, o estado do objeto da entidade de nível superior é alterado para Modified.

As alterações não são rastreadas quando os objetos estão em um estado Detached. Os Objetos estão neste estado quando retornados por uma consulta que usa a opção NoTracking ou após serem detached de uma ObjectContext chamando o comando Detach.

Obs: Quando você muda uma associação de uma chave estrangeira, o estado do objeto muda para Modified. Quando você altera uma associação independente, o estado do objeto dependente não muda.

No código estamos usando uma expressão lambda para obter o cliente com código igual a 1 e em seguida alteramos o seu email :

Dim c As Cliente = db.Clientes.First(Function(i) i.Id = 1)
c.email = "macoratti@ig.com.br"

O método SaveChanges efetiva as alterações persistindo-as no banco de dados.

4- Botão de comando Deletar:

 Private Sub btnDeletarObjeto_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles 
btnDeletarObjeto.Click
        Dim db As New ClientesDB
        Dim c As Cliente = db.Clientes.First(Function(i) i.Id = 3)
        db.Clientes.Attach(c)
        db.Entry(c).State = EntityState.Deleted
        db.SaveChanges()
        ConsultaObjetos(db)
    End Sub

No código localizamos o cliente com id igual a 3, anexarmos o cliente ao Contexto e em seguida alteramos o seu estado para Deleted;

Dim c As Cliente = db.Clientes.First(Function(i) i.Id = 3)
db.Clientes.Attach(c)
db.Entry(c).State = EntityState.Deleted

O método SaveChanges efetiva a exclusão persistindo-a no banco de dados.

5- Código do evento Load

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim db As New ClientesDB
        ConsultaObjetos(db)
    End Sub

Aqui apenas criamos uma instância do contexto e chamamos a rotina ConsultaObjetos() para exibir os objetos no ListBox.

Finalmente o código do botão Sair encerra a aplicação:

 Private Sub btnSair_Click(sender As System.Object, e As System.EventArgs) Handles btnSair.Click
        Application.Exit()
    End Sub

Executando o projeto e acionando cada um dos botões de comando iremos obter o seguinte resultado:

Usando o SQL Server Management Studio podemos verificar o banco de dados, as tabelas e os registros incluídos, alterados e excluídos:

Observe que o nome banco de dados é composto pelo nome da solução + o nome da classe definida no contexto : GerenciandoObjetos_EF + ClientesDB

Você percebeu que sem usar nenhuma ferramenta para banco de dados. nenhum comando SQL, sem se preocupar com objetos ADO .NET e apenas definindo classes POCO conseguimos criar o banco de dados, a tabela e gerenciar as informações através do gerenciamento os objetos via Entity Framework.

Pegue o projeto completo aqui: GerenciandoObjetos_EF4.1.zip

Heb 3:5 Moisés, na verdade, foi fiel em toda a casa de Deus, como servo, para testemunho das coisas que se haviam de anunciar;

Heb 3:6 mas Cristo o é como Filho sobre a casa de Deus; a qual casa somos nós, se tão-somente conservarmos firmes até o fim a nossa confiança e a glória da esperança.

Heb 3:7 Pelo que, como diz o Espírito Santo: Hoje, se ouvirdes a sua voz,

Heb 3:8 não endureçais os vossos corações, como na provocação, no dia da tentação no deserto,

Heb 3:9 onde vossos pais me tentaram, pondo-me à prova, e viram por quarenta anos as minhas obras.

Referências:


José Carlos Macoratti