Entity Framework - Usando com aplicação Windows Forms - I


Eu tenho escrito alguns artigos abordando conceitos básicos sobre o Entity Framework e neste artigo vou tratar da utilização do Entity Framework em uma aplicação Windows Forms com um enfoque prático de forma a podermos ir pouco a pouco usando os recursos deste framework; Este artigo se baseia no artigo ADO.NET Entity Framework Tutorial and Basics de mendhak onde eu efetuei alguns ajustes, traduções e adaptações.

Vamos definir o nosso ambiente e as ferramentas usadas:

Nosso objetivo principal será acessar um banco de dados SQL Server e efetuar operações básicas como : consulta, inclusão, alteração e exclusão usando os recursos do Entity Framework.

Vamos iniciar definindo o nosso modelo de dados que será composto pelo banco de dados Editora.mdf, pelas tabelas: Autor, Artigo e Pagamento  e pelas stored procedures DeletaArtigo, GetArtigo, GeArtigos, GetProximoAutor, NovoArtigo, NovoAutor, UpdateArtigo e UpdateAutor que serão criados no SQL Management Studio Express Edition.

Nota: Para saber como o criar um banco de dados e stored procedures no Management Studio veja os artigos:

Abaixo temos a figura que exibe o nosso banco de dados, tabelas e stored procedures criadas:

Começe criando um novo projeto do tipo Windows Forms Application usando a linguagem Visual Basic com o nome ef_Editora;

Com o projeto criado podemos gerar o Entity Data Model-EDM a partir do banco de dados; O EDM será o objeto central a partir do qual iremos realizar todas as operações contra o banco de dados.

O Entity Data Model é um conceito, e o Entity Framework possui uma implementação particular deste modelo que é percebida como um arquivo EDMX em tempo de desenvolvimento. Em tempo de execução o arquivo EDMX é tratado em três arquivos XML separados cada um com um papel definido:
  • .CSDL(Conceptual Schema Definition Language) - (camada conceitual) responsável pelo modelo conceitual;
  • .MLS (Mapping Specification Language) - (camada de mapeamento) responsável pelo mapeamento;
  • .SSDL(Store Schema Definition Language) - (camada de armazenamento) responsável pela persistência;

Clique então com o botão direito do mouse sobre o projeto e selecione a opção Add New Item, e,  a seguir selecione o template ADO .NET Entity Data Model, informe o nome Editora.edmx e clique no botão Add;

A seguir selecione a opção Generate from DataBase pois vamos gerar o modelo a partir do banco de dados Editora.mdf criado anteriormente. Clique em Next>;

Clique no botão New Connection e informe na janela Connection Properties o nome do servidor; no meu caso estou usando o servidor SQL Server Express local, por  isso informei .\SQLEXPRESS.  A seguir selecione o banco de dados Editora e clique no botão OK;

Será apresentada a janela do assistente exibindo a Entity Connection String e a opção para salvar as configurações da entity connection com o nome EditoraEntities no arquivo web.config;vamos aceitar o nome padrão e deixar a opção marcada.EditoraEntities será a nossa referência para o mapeamento e o modelo conceitual.

Observe que a Entity connection string é mais complexa do que uma string de conexão pois ela precisa incluir a string de conexão e a informação adicional sobre o modelo e o provedor. Onde temos:

Selecione agora as tabelas e as stored procedures que serão incluídas em nosso modelo e aceite o nome padrão EditoraModel e clique no botão Finish;

Depois de selecionar os objetos de banco de dados que desejamos incluir no modelo , o assistente do EDM gera o arquivo .edmx - EditoraModelo.edmx que define o modelo e o mapeamento e adiciona as referências ao projeto que são necessárias para o Entity Framework. O arquivo .edmx é uma arquivo XML composto por quatro seções principais:

As stores procedures são adicionados somente à definição SSDL (modelo físico) pois um procedimento armazenado pode interagir com muitas tabelas diferentes e outros objetos em um banco de dados e o Entity Framework não mapeia de forma automática a stored procedure para qualquer entidade específica no CSDL (modelo conceitual). Para criar um método para mapear uma stored procedure podemos editar o arquivo XML.

Abrindo o arquivo .edmx gerado iremos visualizar na representação gráfica do EDM  as entidades criadas conforme a figura a seguir:

in

Observe que não temos exatamente um mapeamento para tabelas do banco de dados, e que a entidade Autor possui um referência a Artigo e Pagamento que foi gerado a partir da chave estrangeira do Modelo de dados pelo assistente.

Agora estamos prontos para usar os recursos do Entity Framework em nossa aplicação Windows Forms. Vamos incluir no formulário form1.vb os componentes:

Os controles deverão ser dispostos conforme o leiaute do form1.vb abaixo:

Vamos iniciar preenchendo controle Combobox - cboAutor com os autores cadastrados na tabela Autor. Para isso primeiro vamos criar uma instância do objectContext e da entidade Pagamento:

'cria uma instância do objectContext e da entidade Pagamento

Dim editoraContext As New EditoraEntities

Dim pagamentoAtual As New Pagamento

 

A classe ObjectContext fornece os recursos para efetuar a consulta e o gerenciamento com dados de entidades como objetos; instâncias de ObjectContext encapsulam a conexão com o banco de dados (EntityConnection), o metadados que descreve o modelo (MetadataWorkspace) e um gerenciador de objetos que rastreia alterações e mantém cache de objetos persistidos (ObjectStateManager).

 

No nosso exemplo criei uma instância chamada editoraContext para representar o nosso ObjectContext.

 

Nota: O tempo de vida do objeto editoraContext deve ser curto, proporcional à unidade de trabalho, que normalmente é uma chamada de método.(Esta é uma recomendação da Microsofot para o DataContext do LINQ To SQL mas que pode ser extendida ao ObjectContext.)

 

Até o momento o EDM suporta um conjunto limitado de tipos primitivos:
  • Bynary,  Byte, Boolean e SByte;
  • Int16,  Int32 e Int64;
  • Decimal, Doube e Single;
  • String(Unicode);
  • Guid;

Portanto nem todos os tipos de dados são suportados em todos os bancos de dados;


A seguir no evento Load vamos definir as propriedades DataSource e DisplayMember do cboAutor conforme abaixo:

 

'define o datasource para a combobox de forma a exibir o nome do autor

cboAutor.DataSource = editoraContext.Autor
cboAutor.DisplayMember =
"Nome"

e finalmente no evento Closing do formulário vamos incluir o código para liberar os recursos usados do Entity Framework:

'libera os recursos usado pelo objectContext

editoraContext.Dispose()

Abaixo temos o código completo do formulário neste momento:

Public Class Form1


'cria uma instância do objectContext e da entidade Pagamento

Dim editoraContext As New EditoraEntities

Dim pagamentoAtual As New Pagamento


Private
Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    'define o datasource para a combobox de forma a exibir o nome do autor

     cboAutor.DataSource = editoraContext.Autor

     cboAutor.DisplayMember = "Nome"

End Sub

 

Private Sub Form1_FormClosing(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing

     'libera os recursos usado pelo objectContext

    editoraContext.Dispose()

End Sub

Executando o projeto iremos verificar que a combobox cboAutor é preenchida com os nomes dos autores da entidade Autor;

Agora vamos incrementar a nossa aplicação exibindo os valores nos controles do formulário para um autor quando o usuário selecionar o autor na combobox. A navegação esta sendo feita pela combobox, e conforme um autor é selecionados seus dados serão exibidos no formulário. Isso pode funcionar para uma quantidade pequena autores se houver uma quantidade muito grande teríamos outras formas mais convenientes de efetuar a navegação.

No código abaixo , que esta comentado, para cada autor selecionado os valores correspondentes de Código de Pagamento e de Salário serão exibidos no formulário:

Private Sub cboAutor_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboAutor.SelectedIndexChanged


'Obtemos o objeto Autor selecionado a partir da combobox

Dim autorSelecionado As Autor = CType(cboAutor.SelectedItem, Autor)

 

'Obtem o ID do autor selecionado

Dim autorSelecionadoID As Integer = autorSelecionado.AutorID

 

'efetua uma consulta na entidade Pagamento selecionando os pagamentos para o autor com o ID selecionado

Dim consultaPagamento As IQueryable(Of Pagamento) = From p In editoraContext.Pagamento _

                                                                                    Where p.Autor.AutorID = autorSelecionadoID _

                                                                                                                Select p

 

'Obtem a lista de pagamentos para o autor

Dim pagamentoSelecionado As List(Of Pagamento) = consultaPagamento.ToList()

 

'Se algum pagamento for encontrado então exibe  primeiro pagamento

If (Not pagamentoSelecionado Is Nothing AndAlso pagamentoSelecionado.Count > 0) Then

          pagamentoAtual = pagamentoSelecionado.First()

Else

           pagamentoAtual = Nothing

End If

 

preencherCampos()

 

End Sub

 

Após isso chamamos a rotina preencherCampos() que atribui os valores aos controles do formulário:

Private Sub preencherCampos()

 

If Not pagamentoAtual Is Nothing Then

    lblCodPagamento.Text = pagamentoAtual.PagamentoID.ToString()

    numSalario.Value = Convert.ToDecimal(pagamentoAtual.Salario)

    btnIncluir.Enabled = False

    btnDeletar.Enabled = True

    btnAtualizar.Enabled = True

Else

    lblCodPagamento.Text = "Sem pagamento"

    numSalario.Value = 0

    btnIncluir.Enabled = True

    btnDeletar.Enabled = False

    btnAtualizar.Enabled = False

End If

End Sub

Executando o projeto novamente e selecionando um autor iremos obter:

Agora vamos mostrar como podemos gerenciar as informações efetuando as operações para atualizar, incluir e deletar informações de autores cadastrados.

1- Atualizando informações

Neste exemplo somente o salário do autor poderá ser atualizado. Para isso vamos usar o evento Click do botão Atualizar com o código a seguir:

Private Sub btnAtualizar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAtualizar.Click

 

   pagamentoAtual.Salario = Convert.ToInt16(numSalario.Value)

 

   Dim linhasAfetadas As Integer = editoraContext.SaveChanges()

 

   MessageBox.Show(linhasAfetadas .ToString() + " alterações efetivadas na tabela")

 

End Sub

Estamos definindo a propriedades Salario do pagamento atual com o valor informando no controle numericUpDown - numSalario e em seguida usando o método SaveChanges do ObjectContext editoraContext para persistir todas as atualizações para a fonte de dados e resetar as alterações no objectContext.

Nota: Não esta explícito na documentação mas tudo indica que quando invocamos SaveChanges a atualização é encapsulada em uma transação.

2- Deletando informações

Para excluir informações usamos o método DeleteObject(obj) passando o objeto que desejamos excluir. O código para o nosso exemplo esta mostrado a seguir no evento Click do botão Deletar:

Private Sub btnDeletar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDeletar.Click

     'marca o objeto para ser excluído

    editoraContext.DeleteObject(pagamentoAtual)
    'exclui o objeto marcado

    editoraContext.SaveChanges(True)

    pagamentoAtual = Nothing

    preencherCampos()
 

End Sub

O método DeleteObject() marca o objeto para deleção a partir do ObjectStateManager, sendo que o objeto é efetivamente excluído quando o método SaveChanges é chamado.

3- Incluindo novas  informações

Para incluir novas informações sobre o pagamento a um autor criamos uma instância da entidade Pagamento e em seguida obtemos o autor selecionado efetuando uma coerção forçada para o tipo Autor (Ctype).

Private Sub btnIncluir_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnIncluir.Click

 

  Dim novoPagamento As New Pagamento()

   Dim autorSelecionado As Autor = CType(cboAutor.SelectedItem, Autor)

 

  novoPagamento.Autor = autorSelecionado

  novoPagamento.Salario = Convert.ToInt16(numSalario.Value)
 

  editoraContext.AddToPagamento(novoPagamento)

  editoraContext.SaveChanges()
 

  pagamentoAtual = novoPagamento

 

  preencherCampos()

 

End Sub

Em seguida atribuímos o autor selecionado e o salário informado à instância de Pagamento.

Para incluir o novo pagamento usamos o método addToPagamento() passando a instância de Pagamento com os valores atualizados. O Entity Framework define a ordem através do relacionamento entre as chaves primárias e estrangeiras das tabelas Autor e Pagamento.

Para persistir todas as novas informações para a fonte de dados e resetar as alterações no objectContext usamos o método SaveChanges() e exibimos os campos com os novos valores.

Naturalmente deveremos primeiro incluir um novo autor para em seguida atribuir um pagamento ao mesmo. No próximo artigo eu irei mostrar como efetuar o gerenciamento das informações para autores.

Pegue o projeto completo aqui : ef_Demo1.zip

Aguarde a continuação deste artigo no link: Entity Framework - Usando entidades do EDM com Windows Forms II

Referências:


José Carlos Macoratti