Entity Framework - Revisitando o DataBinding
A vinculação de dados - DataBinding - na plataforma .NET é uma poderosa característica que permite que elementos visuais no cliente seja conectados a uma fonte de dados como DataSet , DataViews , arrays , etc. Alguns destes elementos visuais no cliente podem ser TextBox , ListBox , ComboBox , DataGrid , etc. Uma comunicação em duas vias é realizada de maneira que qualquer alteração feita na fonte de dados seja refletida imediatamente no elemento visual.
Pois bem o é possível realizarmos o DataBinding com o Entity Framework e neste artigo eu vou mostrar como isso é bem simples de ser feito.
Vantagens do DataBinding
Desvantangens do DataBinding
Vamos então mostrar na prática como podemos usar o Databinding com o Entity Framework.
Para os exemplos deste artigo eu estou usando o Visual Basic 2010 Express Edition e a versão 4.0 do Entity Framework e o banco de dados Northwind.mdf do SQL Server 2008 Express Edition.
Abra o VB 2010 Express Edition e crie um novo projeto do tipo Windows Forms Application com o nome EF_DBinding;
Com o projeto criado vamos dar o primeiro passo para usar o Entity Framework incluindo um Entity Data Model(EDM) no projeto.
O
EDM é um modelo entidades -
relacionamentos onde:
É a partir do modelo de entidades
que podemos escrever código usando as diferentes APIs,
como o provedor EntityClient ou o Object
Services com LINQ to Entities |
Embora na versão 4.0 o Entity Framework agora temos o suporte a POCO realmente funcional, neste artigo eu vou usar o mapeamento gerado pelo EF através do entity data Model (EDM).
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. |
No menu Project selecione Add New Item e na janela do assistente selecione o modelo ADO .NET Entity Data Model e informe o nome Northwind.edmx clicando no botão Add;
Selecione o item : Generate From DataBase e clique em Next>;
Defina a conexão com o banco de dados Northwind.mdf e aceite o nome padrão para a entity connection e clique em Next>;
Na próxima janela do assistente selecione as tabelas Customers e Orders marcando as opções conforme mostra a figura abaixo e aceitando o nome padrão para o modelo;
Clique em Finish;
Note que estamos optando por marcar as opções para incluir a chave estrangeira no modelo e pluralizar ou singularizar os nomes dos objetos gerados.
A opção - Include foreign key columns in the model - irá incluir a coluna chave estrangeira da tabela. Se você não selecionar esta opção ainda poderá realizar esta definição posteriormente no relacionamento entre as tabelas. |
Ao final teremos o EDM - Northwind.edmx - gerado consistindo das entidades Customer e Order onde temos o mapeamento para as tabelas Customers e Orders e todo o suporte necessário para realizar a persistência através das operações CRUD(Create,Update,Delete);
Agora que temos o EDM devemos criar no projeto um novo Data Source.
No menu Data selecione Add New Data Source...
No assistente selecione a opção Object e clique em Next>;
Na janela seguinte expanda os objetos referenciados e selecione o objeto Customer e clique em Finish;
Ao final você deverá ver na janela Data Sources os objetos Customer e Orders conforme a figura a seguir:
Dessa forma já temos toda a infra-estrutura montada para usar o DataBinding com o Entity Framework, observe que até o momento estamos usando apenas o recurso arrastar e soltar;
Vamos voltar ao formulário form1.vb do projeto que criamos no início e vamos incluir neste formulário os seguintes controles:
A seguir defina o seguinte leiaute no formulário usando estes controles:
Com a interface definida podemos partir para a definição do DataBinding.
Primeiro vamos vincular a entidade Customer ao controle ComboBox - cboCustomers - de forma a exibir todos os clientes (customers) da tabela Customers;
Selecione o formulário form1.vb e clique no ícone View Code da janela Solution Explorer para abrir a janela de código do formulário;
No início do formulário , logo após a definição do mesmo, vamos incluir a linha de código que irá criar uma instância do nosso Context gerado pelo EDM;
Dim db As New NORTHWNDEntities
O nosso contexto chama-se NORTHWNDEntities e através dele poderemos usar todos os recursos gerados no EDM;
No Entity Framework, 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). Cada objeto retornado por uma consulta seja usando LINQ to Entities ou Entity SQL será automaticamente anexado a um ObjectContext. |
A seguir no evento Load do formulário form1.vb vamos incluir o código que irá preencher a combobox com o nome do Contato dos clientes - ContactName;
Private
Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load cboCustomers.DataSource = db.Customers.ToList() cboCustomers.ValueMember = "CustomerID" cboCustomers.DisplayMember = "ContactName" End Sub |
O código define a fonte de dados do controle ComboBox definindo uma consulta LINQ to Entities que retorna todos os objetos da entidade Customer;
Estamos exibindo o nome do contato- ContactName - na combobox e usando a chave CustomerID como valor selecionado;
Para refletir no controle DataGridView - gdvOrders - os pedidos (orders) de cada cliente selecionado na combobox vamos usar o evento SelectedIndexChanged, de forma que feita uma seleção no controle o evento será disparado.
Inclua no evento o seguinte código:
Private
Sub cboCustomers_SelectedIndexChanged(ByVal sender As
System.Object, ByVal e As System.EventArgs) Handles
cboCustomers.SelectedIndexChanged Dim codigo As String = "" Try codigo = cboCustomers.SelectedValue If codigo <> String.Empty Then Dim pedidos = From p In db.Orders Where p.CustomerID = codigo Select p.OrderID, p.OrderDate, p.Freight, p.ShipCountry gdvOrders.DataSource = pedidos.ToList lblPedidos.Text = pedidos.Count End If Catch ex As Exception MessageBox.Show("Erro : " ex.Message) End Try End Sub |
Vamos entender o código acima:
- obtemos o código do cliente (CutomserID) selecionado na combobox: codigo = cboCustomers.SelectedValue
- Se o código não for vazio então realizamos uma consulta LINQ to Entities :
Dim pedidos = From p In db.Orders Where p.CustomerID = codigo Select p.OrderID, p.OrderDate, p.Freight, p.ShipCountry
- Esta consulta retorna os pedidos do cliente selecionando retornando apenas os campos: OrderID, OrderDate, Freight, ShipCountry;
- Atribuímos o a relação de objetos pedidos retornados a propriedade DataSource do DataGridView;
- Contamos o número de pedidos retornados exibindo o valor em um controle Label : lblPedidos.Text = pedidos.Count
O resultado pode ser visto na figura abaixo:
Que tal dar uma incrementada no projeto de forma que ao clicar em um pedido do DataGridView tivéssemos mais informações do pedido exibidas em outro formulário ?
Vamos lá...
Inclua um novo formulário no projeto : Menu Project -> Add Windows Forms , aceite o nome padrão form2.vb;
A seguir vamos incluir neste formulário 6 controles Labels, controles TextBox e um controle Button conforme o leiaute abaixo:
A idéia é preencher este formulário com os dados de um pedido selecionado no formulário form1.vb;
Pois bem, vamos voltar ao formulário form1.vb e no evento CellClick do controle gdvOrders incluir o seguinte código:
Private
Sub gdvOrders_CellClick(ByVal sender As System.Object,
ByVal e As
System.Windows.Forms.DataGridViewCellEventArgs) Handles
gdvOrders.CellClick Dim orderid As Integer = Convert.ToInt32(gdvOrders.Rows(e.RowIndex).Cells(0).Value) Dim frm As Form2 = New Form2(orderid) frm.Show() End Sub |
- primeiro obtemos o valor do código do pedido (OrderID) da linha selecionada no DataGridView;
- em seguida criamos uma instância do formulário form2 passando o código do pedido e exibimos o formulário;
Então vamos voltar ao bendito formulário form2.vb e ajustá-lo para receber o parâmetro OrderID;
No formulário form2.vb vamos definir um construtor que vai receber o parâmetro com o seguinte código:
Public
Sub New(ByVal codigo As Integer) ' This call is required by the designer. InitializeComponent() ' Add any initialization after the InitializeComponent() call. codigoPedido = codigo End Sub |
a variável codigoPedido deve ser declarada no início do formulário: Dim codigoPedido As Integer
Agora vamos usar o evento Load do formulário form2.vb para preencher os controles com os detalhes do pedido selecionado.
Private
Sub Form2_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load Using context As New NORTHWNDEntities Dim pedido = context.Orders.Single(Function(p) p.OrderID = codigoPedido) preenchecontroles(pedido) End Using End Sub |
Estamos usando uma instância do ObjectContext e realizando uma consulta para retornar um único pedido com base no código do pedido selecionado:
Dim pedido = context.Orders.Single(Function(p) p.OrderID = codigoPedido)
A seguir chamamos a rotina preencheControles() passando o pedido obtido na consulta LINQ;
A rotina preencheControles() possui o seguinte código:
Private
Sub preenchecontroles(ByVal pedido As Order) txtCodigo.Text = pedido.OrderID txtData.Text = pedido.OrderDate txtFrete.Text = pedido.Freight txtPais.Text = pedido.ShipCountry txtCidade.Text = pedido.ShipCity txtRegiao.Text = pedido.ShipRegion End Sub |
O código da rotina apenas exibe os valores do objeto Pedido obtido da consulta. O resultado pode ser visto na figura abaixo:
Bem, neste momento você pode estar pensando: "Mas que raios de DataBinding é esse que eu tenho que digitar código ??? Cadê o arrastar e soltar ???
Calma , agora eu vou exibir em um outro formulário os dados dos clientes e seus respectivos pedidos em uma exibição Mestre-Detalhes usando o DataSource criado e arrastando os objeto diretamente para o formulário;
Inclua um novo formulário no projeto : Menu Project -> Add Windows Forms , aceite o nome padrão form3.vb;
Abra o formulário form3.vb e a janela DataSource;
A seguir na janela DataSource defina o modo de exibição do objeto Customer como Details:
Após isso arraste e solte o objeto Customer diretamente no formulário form3.vb dispondo os campos conforme a figura abaixo:
A seguir selecione o objeto Orders (modo DataGridView) e arraste e solte-o no formulário conforme a figura abaixo:
Observe que foi criada a barra de navegação e os objetos : CustomerBindingSource, CustomerBindingNavigator e OrdersBindingSource;
Para podemos realizar a vinculação de dados entre os controles e a fonte de dados temos que incluir o seguinte código no formulário:
Dim db As
NORTHWNDEntities Private Sub Form3_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load db = New NORTHWNDEntities CustomerBindingSource.DataSource = db.Customers.OrderBy(Function(c) c.CustomerID) End Sub |
Executando o projeto e abrindo o formulário veremos o databinding em ação conforme figura abaixo:
Existem outros recursos que podemos implementar usando o DataBinding com o Entity Framework mas isso fica para outro artigo.
Pegue o projeto completo aqui: EF_DBinding.zip
Eu sei é apenas VB .NET, mas eu gosto...
Referências: