Entity Framework 4 - Operações básicas de acesso a dados - 2
Na primeira parte deste artigo apresentei os objetivos e criei toda a infra-estrutura para que possamos nesta segunda parte ir ao que interessa. |
Eu realizei uma pequena alteração a interface apresentada na primeira parte para tornar mais intuitiva a interação com usuário dessa forma eu incluir um formulário MDI que será o formulário principal e no formulário de vendas eu incluir um controle TabControl com duas abas :
Ficou assim:
Vamos agora continuar focando o formulário de registro de pedidos onde iremos usar os recursos do Entity Framework(EF) para acessar e persistir as informações na nossa base de dados usando as entidades do modelo de entidades criado pelo Entity Data Model(EDM).
Ao carregar e aplicação e chamar o formulário de Vendas temos o seguinte resultado:
Note que :
- No controle ListBox estão sendo
exibidos os clientes cadastrados; Vejamos como acessar essa informações e preencher estes controles usando Entity Framework. Para começar no início do formulário iremos definir a referência ao projeto Persistencia; using Persistencia;A seguir vamos definir a variável ctx do tipo ObjecContext, nosso caso o ObjectContext possui o nome JcmSoftEntities. Definirmos também duas variáveis para controlar o código do produto e do cliente; JcmSoftEntities ctx = null;int idProduto; int idCliente; |
Para preencher os controles listbox1 e combobox1 (eu estou usando os nomes padrões mas recomendo que você use nomes próprios) vamos usar o evento Load do formulário definindo nele o seguinte código:
private void Form1_Load(object sender, EventArgs e) { ctx = new JcmSoftEntities(); comboBox1.DisplayMember ="nome"; //selecteditem comboBox1.ValueMember = "produtoid"; //selectedvalue comboBox1.DataSource = ctx.Produtos; listBox1.DataSource = ctx.Clientes; listBox1.DisplayMember = "nome"; listBox1.ValueMember = "clienteid"; //dataGridView1.DataSource = ctx.Detalhes; } |
No código acima primeiro criarmos uma instância do nosso Contexto representado por JcmSoftEntities, é através do contexto que teremos acesso as entidades e aos seus métodos e poderemos também persistir as informações nos objetos e na base de dados.
A seguir usei a propriedade DisplayMember e ValueMember dos controles para definir o que será exibido no controle , em ambos os casos a propriedade nome, e também o valor que será usado quando um item for selecionado do controle, no caso o código do produto e do cliente.
A propriedade DataSource define a fonte das informações no caso as entidades Produtos e Clientes do Contexto.
Nota: O código comentado : dataGridView1.DataSource = ctx.Detalhes permite exibir os detalhes dos pedidos dos clientes no controle dataGridView1 da aba Pedidos - Cliente.
Notou que não precisamos nos preocupar em definir os objetos para conexão nem os objetos como dataadpater, dataset, datareader e nem comandos SQL. Graças ao Entity Framework.
Para definir o pedido devemos selecionar um cliente e um produto e ao fazer essa seleção teremos os demais controles do formulário preenchidos. Assim ao selecionar um cliente os controles TextBox Nome e Endereço são preenchidos com informações do cliente.
Da mesma forma ao selecionar um produto o seu preço será preenchido no controle TextBox.
Fazemos isso usando o evento SelectedIndexChanged dos controles ListBox e Combobox. Neste evento temos o seguinte código:
private void listBox1_SelectedIndexChanged(object sender, EventArgs e) { if (int.TryParse(listBox1.SelectedValue.ToString(), out idCliente)) { using (var ctx = new JcmSoftEntities()) { var cliente = ctx.Clientes.First(c => c.clienteid == idCliente); txtNomeCliente.Text = cliente.nome; txtEnderecoCliente.Text = cliente.endereco; } } }
|
ListBox - Clientes |
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { if (int.TryParse(comboBox1.SelectedValue.ToString(), out idProduto)) { using (var ctx = new JcmSoftEntities()) { var produto = ctx.Produtos.First(p => p.produtoid == idProduto); txtPrecoProduto.Text = String.Format("{0:#,###.##}", produto.preco.ToString()); } } }
|
ComboBox - Produtos |
O código é idêntico e nele primeiro obtemos o id do cliente e do produto selecionado e depois efetuamos uma busca pelo cliente/produto :
var cliente = ctx.Clientes.First(c => c.clienteid == idCliente); |
var produto = ctx.Produtos.First(p => p.produtoid == idProduto); |
Nesta consulta LINQ estamos usando o operador First que retorna o primeiro elemento da seqüência que satisfaz o critério definido na expressão lambda;
O que são
Expressões Lambda ?
As expressões lambda foram incluídas no VS/VB 2008/C# para dar suporte a consultas LINQ. As cláusulas Where são assim compiladas como expressões lambdas e chamadas em itens aplicáveis do seu dataset. Podem ser consideradas uma forma de delegate que pode passar ou retornar outra função. Nota: Delegates permitem que uma classe use métodos de outra classe. Para saber mais sobre delegates leia o meu artigo: Usando Delegates No LINQ as expressões lambda
são usadas para realizar ações sobre listas de objetos e com métodos de
extensão. |
A seguir exibimos as respectivas informações nos controles TextBox do formulário.
Após selecionar o cliente e o produto basta informar a quantidade e a data do pedido basta clicar no botão - Confirmar Pedido - para persistir as informações do pedido nas entidades.
Para isso usamos o evento Click do botão inserindo nele o seguinte código:
private void btnConfirmarPedido_Click(object sender, EventArgs e) { if (!nupdQuantidade.Text.Equals("") || !dtpDataPedido.Value.Equals("") || txtNomeCliente.Text.Equals("")) { Pedido pedido = new Pedido(); pedido.clienteid = idCliente; pedido.datapedido = Convert.ToDateTime(dtpDataPedido.Value); ctx.AddToPedidos(pedido); Detalhe detalhe = new Detalhe(); detalhe.produtoid = idProduto; detalhe.preco = Convert.ToDecimal(txtPrecoProduto.Text); detalhe.quantidade = Convert.ToInt32(nupdQuantidade.Text); detalhe.Pedido = pedido; AtualizaEstoque(detalhe); try { ctx.SaveChanges(); MessageBox.Show("Pedidos Gravado com sucesso."); } catch( Exception ex ) { MessageBox.Show("Erro : " + ex.InnerException.ToString()); } } else { MessageBox.Show("Dados inválidos."); } } |
Vamos entender o que este código faz:
- Primeiro verificamos se foi informada a quantidade, a data do pedido e se um cliente foi selecionado;
- Em seguida criamos um instância da entidade Pedido() e atribuímos os valores do id do cliente selecionado e da data do pedido informada as propriedades clienteid e datapedido da entidade;
- Depois usamos o método AddToPedidos para incluir o novo objeto Pedido na coleção de objetos: ctx.AddToPedidos(pedido);
Você
pode incluir novos objetos a um contexto de objeto através do método
AddObject ou chamando um dos métodos AddToEntitySetName do
ObjectConext. Você também pode incluir um objeto a um contexto de objeto adicionando o objeto a um EntityCollection existente. Quando você chama o método Add em um EntityCollection que esta anexada a um contexto de objeto , o objeto que você esta incluindo é adicionado ao mesmo ObjectContext. |
Na linha de código ctx.AddToPedidos(pedido) o método AddTo<EntityName>, que é usado pelo EF baseado nas entidades geradas a partir do banco de dados,e , irá realizar a inclusão do novo objeto no contexto.
Repetimos a operação para a entidade Detalhe definindo os valores do id do produto , preço e quantidade e a seguir atribuímos o pedido criado ao detalhe do pedido: detalhe.Pedido = pedido;
Antes de persistimos as informações chamamos o método AtualizaEstoque(detalhe); que irá atualizar o estoque do produto que foi vendido.
Este método possui o seguinte código:
private void AtualizaEstoque(Detalhe detalhe) { var produto = ctx.Produtos.First(p => p.produtoid == detalhe.produtoid); int quantidadePedido = Convert.ToInt32(detalhe.quantidade); int estoqueProduto = Convert.ToInt32(produto.estoque); produto.estoque = estoqueProduto - quantidadePedido; ctx.Produtos.ApplyCurrentValues(produto); } |
Observe que neste código procuramos pelo produto que esta sendo feito o pedido usando uma consulta LINQ com operador First e expressão lambda;
Em seguida atualizamos o estoque subtraindo a quantidade do pedido do estoque do produto.
Para podermos persistir esta informação na entidade usamos o método ApplyCurrentValues(produto);
O método ApplyCurrentValues(TEntity) copia os valores escalares a partir do objeto fornecido para o objeto no ObjectContext que possui a mesma chave.
Este método é usado para aplicar as mudanças que foram feitas a objetos fora do ObjectContext, tais como um objeto desanexado (detached) que são recebidos por um web service. (Você pode usar o EntityKey do objeto detached para retornar uma instância deste objeto a partir da fonte de dados.)
Após isso usamos o método SaveChanges() do contexto para persistir as alterações nas entidades e replicar no banco de dados.
Para encerrar preciso falar sobre a exibição dos detalhes do pedido na aba - Pedidos - Cliente.
Ao clicar no botão - Mostra Pedidos - no evento Click deste botão temos o seguinte código:
private void btnMostraPedidos_Click(object sender, EventArgs e) { tabVendas.SelectTab("tabPage2"); MostraPedidosCliente(); } |
Primeiro selecionamos e ativamos aba - tabPage2 - que é a aba Pedidos - Cliente;
Em seguida chamamos o método MostraPedidosCliente() que possui o seguinte código:
private void MostraPedidosCliente() { var consulta = from dep in ctx.Detalhes.Include("Produtos") where dep.Pedido.clienteid == idCliente select new { dep.Produto.nome, dep.quantidade, dep.preco, dep.Pedido.datapedido }; dataGridView1.DataSource = consulta.ToList(); dataGridView1.Refresh(); }
|
Este método realiza uma consulta LINQ onde selecionamos os detalhes de um pedido para o cliente selecionado (idCliente) e em seguida exibe o resultado no controle DataGridView.
Como você pode acompanhar realizar tarefas básicas mas de rotina em aplicações com acesso a dados de uma forma bem simples usando um código enxuto e deixando todo o trabalho de para o Entity Framework. Tivemos somente o trabalho de prepará-lo para ser usado com o modelo de dados do projeto.
Esse um dos muitos motivos para considerar a utilização do Entity Framework em suas aplicações de acesso a dados. É claro que nem sempre ele será a opção mais recomendada pois cada projeto tem suas características e particularidades mas é muito importante você conhecer como ele funciona para poder tomar essa decisão.
Pegue o projeto completo aqui: ef4_Operacoes_BD.zip
Eu sei é apenas Entity Framework mas eu gosto...
Referências: