Professional Documents
Culture Documents
Net)
sexta-feira, 20/05/2011 s 10h05, por Jos Carlos Macoratti Adicione o recurso da traduo ao seus programas VB.NET. Use o tradutor de sites do Google em seus programas e oferea acesso instantneo a tradues automticas. Comece informando o texto a traduzir, depois escolha o idioma de destino para a traduo e pronto! Seu texto ser traduzido usando o Google Translate.
O projeto Visual Basic usa os controle WebBrowser, ProgressBar, ToolStip, NotifyIcon e ContextMenu. A aplicao tambm usa o componente OSSkin.Net que permite utilizar Skins em aplicaes .NET. O componente OSSkin.Net permite que os desenvolvedores usem o recurso de skins em aplicaes Windows Forms na plataforma .NET a partir de uma escolha de 18 estilos, incluindo Windows XP, Vista, o Aero, Office 2007 e temas Mac OS-X. Graas aos recursos avanados concebidos inteiramente em C#, ele o nico produto disponvel atualmente que permite mudar completamente a aparncia de todas as formas de janelas,formulrios, controles e dilogos. O cdigo da aplicao trivial, veja abaixo o exemplo da chamada para a converso Ingls -> Portugus:
Pegue o projeto completo: TradutorGoogle.zip Simples assim! Eu sei, apenas VB .NET, mas eu gosto
Nosso objetivo ser atualizar as tabelas Orders e Orders Details com informaes obtidas de um formulrio que simular o envio de um pedido e seus detalhes. Embora as demais tabelas no sejam atualizadas, iremos precisar de suas informaes. Neste artigo eu vou mostrar como realizar esta tarefa usando ADO .NET e seus objetos; e na segunda parte irei mostrar como fica a mesma tarefa sendo realizada com os recursos do LINQ to SQL. Alm de revisarmos os conceitos relacionados com os objetos bsicos da ADO .NET, como DataReader, DataAdapter e SqlCommand. Iremos trabalhar com classes, transaes e instrues SQL parametrizadas. Como temos o modelo de dados j pronto, eu vou iniciar mostrando como ser o formulrio de entrada de dados usado na aplicao. Os recursos necessrios para acompanhar este artigo so:
Visual Basic 2010 Express Edition SQL Server 2008 Express Banco de dados Northwind.mdf
2 Combobox cboClientes e cboFuncionarios 5 TextBox txtID, txtProduto (ReadOnly=True), txtPreco (ReadOnly=True), txtQtde, txtSubtotal (ReadOnly=True) 2 ListView ListView1 e ListView2 2 TextBox txtItems e txtTotal 4 TextBox txtNome, txtEndereco, txtCidade e txtRegiao 2 Buttons btnSalvar e btnNovo
Os dois controles Combobox devero ser preenchidos quando o formulrio for carregado, permitindo que o usurio selecione o cliente e o funcionrio. A seguir, o usurio dever informar o cdigo do produto e, ao teclar ENTER, ser realizada uma busca e o nome do produto e seu preo unitrio ser exibido, bastando ao usurio informar a quantidade desejada para que o valor total seja calculado e o novo pedido exibido no controle ListView.
A seguir, o usurio deve informar os dados do destinatrio: Nome, Endereo, Cidade e Regio e clicar no boto Salvar Pedido para persistir os dados do novo pedido e seus detalhes. Este cenrio muito frequente em aplicaes comerciais. Vamos, ento, mostrar como implementar o cdigo das funcionalidades envolvidas nesta operao.
Classe NWProduto
No menu Project, clique em Add Class e selecione o template Class informando o nome NWProduto:
Digite o cdigo abaixo na classe NWProdutos; nele estamos definindo trs variveis com o mesmo nome dos campos da tabela Products e o mtodo getProdutoPorId() que retorna uma lista de produtos:
Public Class NWProduto Public ProductID As Integer Public ProductName As String Public ProductPrice As Decimal Public Shared Function getProdutoPorId(ByVal productID As String) As List(Of NWProduto) Dim produtos As New List(Of NWProduto) Dim CN As New SqlClient.SqlConnection(strConexao) Dim CMD As New SqlClient.SqlCommand Dim RDR As SqlClient.SqlDataReader If IsNumeric(productID) Then CMD.CommandText = "SELECT * FROM products WHERE ProductID=@ProductID" CMD.CommandType = CommandType.Text CMD.Parameters.AddWithValue("@ProductID", productID) CMD.Connection = CN CN.Open() RDR = CMD.ExecuteReader Dim prod As NWProduto = Nothing If RDR.Read Then prod = New NWProduto prod.ProductID = RDR.GetInt32(RDR.GetOrdinal("ProductID")) prod.ProductName = RDR.GetString(RDR.GetOrdinal("ProductName")) prod.ProductPrice = RDR.GetDecimal(RDR.GetOrdinal("UnitPrice")) produtos.Add(prod) End If Else CMD.CommandText = "SELECT * FROM Products WHERE ProductName LIKE '%' + @ProductID + '%'" CMD.CommandType = CommandType.Text CMD.Parameters.AddWithValue("@ProductID", productID) CMD.Connection = CN CN.Open() RDR = CMD.ExecuteReader While RDR.Read Dim prod As New NWProduto prod.ProductID = RDR.GetInt32(RDR.GetOrdinal("ProductID")) prod.ProductName = RDR.GetString(RDR.GetOrdinal("ProductName")) prod.ProductPrice = RDR.GetDecimal(RDR.GetOrdinal("UnitPrice")) produtos.Add(prod) End While End If CN.Close() Return produtos End Function
End Class
Classe NWFuncionario
Repita o procedimento feito para criar a classe NWProduto e crie a classe NWFuncionario. Nesta classe definimos duas variveis, o mtodo GetTodosFuncionarios(), que retorna uma lista de funcionrios, e sobrescrevemos o mtodo ToString() que agora retorna o nome do funcionrio.
Public Class NWFuncionario Public EmployeeID As Integer Public EmployeeName As String Public Overrides Function ToString() As String Return EmployeeName End Function Public Shared Function GetTodosFuncionarios() As List(Of NWFuncionario) Dim CMD As New SqlClient.SqlCommand Dim Funcionarios As New List(Of NWFuncionario) CMD.CommandText = "SELECT * FROM Employees" CMD.CommandType = CommandType.Text Dim CN As New SqlClient.SqlConnection(strConexao) CMD.Connection = CN CN.Open() Dim RDR As SqlClient.SqlDataReader RDR = CMD.ExecuteReader() While RDR.Read Dim Emp As New NWFuncionario Emp.EmployeeID = RDR.GetInt32(RDR.GetOrdinal("EmployeeID")) Emp.EmployeeName = RDR.GetString(RDR.GetOrdinal("LastName")) & " " & RDR.GetString(RDR.GetOrdinal("FirstName")) Funcionarios.Add(Emp) End While RDR.Close() Return Funcionarios End Function End Class
Classe NWCliente
Repita o procedimento feito para criar a classe NWProduto e crie a classe NWCliente. Nesta classe, vamos definir duas variveis, sobrescrever a funo ToString e definir o mtodo GetTodosClientes que retorna uma lista de Clientes:
Public Class NWCliente Public CustomerID As String Public CustomerName As String Public Overrides Function ToString() As String Return CustomerName End Function Public Shared Function GetTodosClientes() As List(Of NWCliente) Dim CMD As New SqlClient.SqlCommand Dim Clientes As New List(Of NWCliente) CMD.CommandText = "SELECT * FROM Customers" CMD.CommandType = CommandType.Text Dim CN As New SqlClient.SqlConnection(strConexao) CMD.Connection = CN CN.Open() Dim RDR As SqlClient.SqlDataReader RDR = CMD.ExecuteReader() While RDR.Read Dim Cust As New NWCliente Cust.CustomerID = RDR.GetString(RDR.GetOrdinal("CustomerID"))
Cust.CustomerName = RDR.GetString(RDR.GetOrdinal("CompanyName")) Clientes.Add(Cust) End While RDR.Close() Return Clientes End Function End Class
Classe NWPedido
Repita o procedimento feito para criar a classe NWProduto e crie a classe NWPedido. Note que no interior da classe NWpedido temos a definio da classe NWPedidoDetalhes que representa os detalhes de um pedido. O mtodo SalvarPedido() recebe um novo pedido e realiza uma transao para salvar o pedido na tabela Orders e os seus detalhes tabela Order Details:
Public Class NWPedido Public Class NWPedidoDetalhes Public ProductID As Integer Public ProductPrice As Decimal Public ProductQuantity As Integer Public ProductDiscount As Decimal End Class Public Public Public Public OrderDate As Date EmployeeID As Integer CustomerID As String Detalhes As New List(Of NWPedidoDetalhes)
Public Shared Function SalvarPedido(ByVal novoPedido As NWPedido) As Integer Dim CN As New SqlClient.SqlConnection(strConexao) Dim CMD As New SqlClient.SqlCommand CN.Open() CMD.Connection = CN Dim TR As SqlClient.SqlTransaction = CN.BeginTransaction CMD.Transaction = TR CMD.CommandText = "INSERT Orders (OrderDate, EmployeeID, CustomerID) VALUES (@orderDate, @employeeID, @customerID);SELECT Scope_Identity()" CMD.Parameters.AddWithValue("@orderDate", Today) CMD.Parameters.AddWithValue("@employeeID", novoPedido.EmployeeID) CMD.Parameters.AddWithValue("@customerID", novoPedido.CustomerID) Dim OrderID As Int32 Try OrderID = System.Convert.ToInt32(CMD.ExecuteScalar) Catch ex As Exception TR.Rollback() CN.Close() Throw ex End Try For Each det As NWPedidoDetalhes In novoPedido.Detalhes CMD.CommandText = "INSERT [Order Details] (OrderID, ProductID, UnitPrice, Quantity) VALUES(@OrderID, @productID, @price, @quantity)" CMD.Parameters.Clear() CMD.Parameters.AddWithValue("@orderID", OrderID) CMD.Parameters.AddWithValue("@productID", det.ProductID) CMD.Parameters.AddWithValue("@price", det.ProductPrice) CMD.Parameters.AddWithValue("@quantity", det.ProductQuantity) Try CMD.ExecuteNonQuery() Catch ex As Exception TR.Rollback() CN.Close() Throw ex End Try Next TR.Commit() CN.Close() Return OrderID
A nossa string de conexo aponta para o banco de dados Northwind.mdf do SQL Server no servidor local SQLExpress. Agora que temos as classes com os mtodos definidos e a string de conexo podemos partir para criar as funcionalidades que iro fazer a aplicao funcionar. No incio do formulrio frmSQL vamos definir um objeto Connection usando a string de conexo definida para se conectar com o banco dados: Dim CN As New SqlClient.SqlConnection(strConexao) No evento Load do formulrio, vamos incluir o cdigo para carregar os dois controles ComboBox:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load cboFuncionarios.DisplayMember = "EmployeeName" cboFuncionarios.ValueMember = "EmployeeID" For Each func As NWFuncionario In NWFuncionario.GetTodosFuncionarios cboFuncionarios.Items.Add(func) Next cboClentes.DisplayMember = "CompanyName" cboClentes.ValueMember = "CustomerID" For Each cli As NWCliente In NWCliente.GetTodosClientes cboClentes.Items.Add(cli) Next End Sub
Vamos criar agora as seguintes rotinas: 1. AdicionarProdutos() inclui as informaes do controle TextBox no controle ListView e chama a rotina AtualizaTotal(); 2. AtualizaTotal() Percorre o ListView e totaliza os produtos; 3. LimpaTextBox() Limpa as caixas de texto; O cdigo das rotinas exibido abaixo:
Private Sub AdicionarProduto() Dim LI As New ListViewItem LI.Text = txtID.Text LI.SubItems.Add(txtProduto.Text) LI.SubItems.Add(txtPreco.Text) LI.SubItems.Add(txtQtde.Text) LI.SubItems.Add(txtSubtotal.Text) ListView1.Items.Add(LI) AtualizaTotal() End Sub
Private Sub AtualizaTotal() Dim items As Integer Dim total As Decimal For Each LI As ListViewItem In ListView1.Items items += Integer.Parse(LI.SubItems(3).Text) total += Decimal.Parse(LI.SubItems(4).Text) Next txtItems.Text = items.ToString txtTotal.Text = total.ToString("#,###.00") End Sub Private Sub LimpaTextBox() txtID.Text = "" txtProduto.Text = "" txtPreco.Text = "" txtQtde.Text = "" txtSubtotal.Text = "" End Sub
Agora, vamos tratar os seguintes eventos do controle ListView1: 1. ColumnWidthChanged Rearranja a largura da coluna do controle ListView1; 2. KeyUp Verifica se foi pressionada a tecla Del ou ESC e conforme o caso, atualiza os totais ou limpa as caixas de textos; 3. SelectedIndexChanged Chama a rotina ExibeDetalhe() O cdigo do tratamento para esses eventos exibido a seguir:
Private Sub ListView1_ColumnWidthChanged(ByVal sender As Object, ByVal e As System.Windows.Forms.ColumnWidthChangedEventArgs) Handles ListView1.ColumnWidthChanged txtItems.Left = ListView1.Left + ListView1.Columns(0).Width + ListView1.Columns(1).Width + ListView1.Columns(2).Width txtItems.Width = ListView1.Columns(3).Width txtTotal.Left = txtItems.Left + txtItems.Width txtTotal.Width = ListView1.Columns(4).Width End Sub Private Sub ListView1_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles ListView1.KeyUp If e.KeyCode = Keys.Delete And ListView1.SelectedItems.Count > 0 Then ListView1.SelectedItems(0).Remove() AtualizaTotal() End If If e.KeyCode = Keys.Escape Then LimpaTextBox() txtID.Focus() End If End Sub Private Sub ListView1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListView1.SelectedIndexChanged ExibeDetalhe() End Sub
A rotina ExibeDetalhe() obtm os dados do controle ListView e exibe-os nos controle TextBox:
Private Sub ExibeDetalhe() If ListView1.SelectedItems.Count > 0 Then txtID.Text = ListView1.SelectedItems(0).Text txtProduto.Text = ListView1.SelectedItems(0).SubItems(1).Text txtPreco.Text = ListView1.SelectedItems(0).SubItems(2).Text txtQtde.Text = ListView1.SelectedItems(0).SubItems(3).Text txtSubtotal.Text = ListView1.SelectedItems(0).SubItems(4).Text End If End Sub
Vamos tratar o evento KeyUp do controle TxtID para que, aps o usurio digitar um cdigo de produto ao pressionar a tecla ENTER, seja feita uma busca na tabela Products e seja obtido os dados do produto que sero exibidos no formulrio:
Private Sub txtID_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles txtID.KeyUp If e.KeyCode = Keys.Enter Then If txtID.Text.Length > 0 Then Dim P As NWProduto Dim todosProdutos As List(Of NWProduto) = NWProduto.getProdutoPorId(txtID.Text.Trim) If todosProdutos.Count = 1 Then txtProduto.Text = todosProdutos(0).ProductName txtPreco.Text = todosProdutos(0).ProductPrice.ToString("#.00") txtQtde.Focus() Else ListView2.Items.Clear() For Each P In todosProdutos Dim LI As New ListViewItem LI.Text = P.ProductID LI.SubItems.Add(P.ProductName) LI.SubItems.Add(P.ProductPrice.ToString("#,###.00")) ListView2.Items.Add(LI) Next If ListView2.Items.Count > 0 Then ListView2.Visible = True ListView2.Items(0).Selected = True ListView2.Capture = True ListView2.Focus() Else txtID.Clear() txtID.Focus() End If End If End If End If If e.KeyData = Keys.Down Then If ListView1.Items.Count > 0 Then LimpaTextBox() ListView1.Items(0).Selected = True ListView1.Focus() End If End If End Sub
Agora, vamos tratar o evento KeyUp do TextBox txtQtde de forma que, aps informar a quantidade e pressionada a tecla ENTER, seja calculado o total e as informaes sejam exibidas no controle ListView configurando assim um novo pedido:
Private Sub txtQty_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles txtQtde.KeyUp If txtProduto.Text.Trim = "" Then MsgBox("Informe o cdigo ou nome do produto!") Exit Sub End If If e.KeyData = Keys.Enter Then Dim qtde As Integer Integer.TryParse(txtQtde.Text, qtde) If qty > 0 Then txtSubtotal.Text = (Decimal.Parse(txtPreco.Text) * qtde).ToString("#,###.00") AdicionarProduto() LimpaTextBox() txtID.Focus() Else txtQtde.Text = "" End If End If If e.KeyData = Keys.Escape Then LimpaTextBox() txtID.Focus() End If
End Sub
No evento Click do boto Salvar Pedido temos o cdigo que salva o pedido e seus detalhes :
Private Sub btnSalvar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSalvar.Click Dim novoPedido As New NWPedido novoPedido.OrderDate = Today novoPedido.CustomerID = CType(cboClentes.SelectedItem, NWCliente).CustomerID novoPedido.EmployeeID = CType(cboFuncionarios.SelectedItem, NWFuncionario).EmployeeID For Each LI As ListViewItem In ListView1.Items Dim novoDetalhe As New NWPedido.NWPedidoDetalhes novoDetalhe.ProductID = LI.Text novoDetalhe.ProductPrice = System.Convert.ToDecimal(LI.SubItems(2).Text) novoDetalhe.ProductQuantity = System.Convert.ToInt32(LI.SubItems(3).Text) novoPedido.Detalhes.Add(novoDetalhe) Next Dim orderID As Integer Try orderID = NWPedido.SalvarPedido(novoPedido) Catch ex As Exception MsgBox("Falha ao gravar o pedido no banco de dados " & vbCrLf & ex.Message) Exit Sub End Try MsgBox("Pedido " & orderID & " gravado com sucesso !") End Sub
No evento Click do boto Novo Pedido apenas limpamos as caixas de texto e colocamos o foco no controle txtID:
Private Sub btnNovo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNovo.Click LimpaTextBox() txtID.Focus() End Sub
Agora s alegria! Vamos executar o projeto e incluir um novo pedido. Aps informar os dados e clicar no boto Salvar Pedido, teremos o seguinte resultado:
Dessa forma, neste projeto tivemos que definir as nossas classes de negcio para poder implementar a funcionalidade desejada. Na segunda parte do artigo iremos implementar a mesma funcionalidade usando o LINQ to SQL e comparar qual das duas mais eficiente.
.NET + Desenvolvimento
Nosso objetivo ser atualizar as tabelas Orders e Orders Details com informaes obtidas de um formulrio que simular o envio de um pedido e seus detalhes. Embora as demais tabelas no sejam atualizadas, iremos precisar de suas informaes.
Como temos o modelo de dados j pronto, eu vou iniciar mostrando como ser o formulrio de entrada de dados usado na aplicao. Os recursos necessrios para acompanhar este artigo so:
Visual Basic 2010 Express Edition; SQL Server 2008 Express; Banco de dados Northwind.mdf.
2 Combobox cboClientes e cboFuncionarios; 5 TextBox txtID, txtProduto (ReadOnly=True), txtPreco (ReadOnly=True), txtQtde, txtSubtotal (ReadOnly=True); 2 TextBox txtItems e txtTotal; 4 TextBox txtNome, txtEndereco, txtCidade e txtRegiao; 2 Buttons btnSalvar e btnNovo.
Os dois controles Combobox devero ser preenchidos quando o formulrio for carregado, permitindo que o usurio selecione o cliente e o funcionrio. A seguir, o usurio dever informar o cdigo do produto e ao teclar ENTER ser realizada uma busca e o nome do produto e seu preo unitrio sero exibidos, bastando ao usurio informar a quantidade desejada para que o valor total seja calculado e o novo pedido exibido no controle ListView.
A seguir, o usurio deve informar os dados do destinatrio: Nome, Endereo, Cidade e Regio e clicar no boto Salvar Pedido para persistir os dados do novo pedido e seus detalhes.
Este cenrio muito frequente em aplicaes comerciais. Vamos, ento, mostrar como implementar o cdigo das funcionalidades envolvidas nesta operao.
O que LINQ ?
LINQ Language integrated Query um conjunto de recursos introduzidos no .NET Framework 3.5 que permitem a realizao de consultas diretamente em base de dados , documentos XML , estrutura de dados, coleo de objetos, etc. usando uma sintaxe parecida com a linguagem SQL.
LINQ to SQL uma implementao especfica to LINQ para o SQL Server que converte consultas escritas em C# ou Visual Basic em SQL dinmico, provendo uma interface que permite mapear os objetos do banco de dados gerando as classes para realizar as operaes usando a sintaxe LINQ; tambm permite realizar alteraes nos objetos e atualizar o banco de dados. Ento, atravs do mapeamento com o LINQ to SQL, nossas classes sero geradas automaticamente e teremos acesso a elas atravs de um contexto gerado em nossa aplicao. Vamos incluir em nosso projeto o recurso LINQ to SQL. Acione o menu Project e clique em Add New Item. Na janela Templates, selecione o item LINQ to SQL Classes alterando o seu nome para Northwind.dbml e clicando no boto Add:
Neste momento ser exibida a janela do descritor Objeto Relacional. Expanda os objetos do banco de dados Northwind.mdf e selecione as tabelas Customers, Employees, Order Details, Orders, Prodcuts arrastando-as e soltandoas na janela Object Relational Designer:
As tabelas do banco de dados sero mapeadas como classes (campos como propriedades, procedures e funes como mtodos) e voc ter no Descritor o conjunto de classes que representam o banco de dados; O arquivo Northwind.dbml contm o arquivo XML com informaes sobre o leiaute das tabelas que foram mapeadas e tambm o descritor contendo as classes geradas pelo mapeamento. Aps encerrar o mapeamento, voc j ter acesso
aos recursos do LINQ To SQL com direito a intellisense completo das informaes referente as tabelas mesmo sem conhecer nada sobre elas. O acesso ser feito atravs da criao de uma instncia da classe DataContext identificada no nosso exemplo como NorthwindDataContext:
Nossa prxima tarefa ser criar uma classe para tratar o contexto e criar os mtodos para acessarem as informaes das classes que foram mapeadas pelo LINQ to SQL.
Vamos incluir uma referncia ao namespace System.Transactions em nosso projeto. No menu Project clique em Add Reference e em seguida clique na guia .NET e selecione o componente System.Transactions e clique em OK:
O namespace System.Transactions contm classes que lhe permitem escrever a sua prpria aplicao transacional e gerenciar os recursos. Voc pode criar e participar em uma transao Local ou distribuda com um mais participantes. Agora vamos definir os seguintes mtodos na classe NWContexto:
GetProdutoPorID() retorna um produto pelo seu cdigo; GetFuncionarios() retorna uma lista de funcionrios; GetClientes() retorna uma lista de clientes; SalvarPedido() salva o pedido no banco de dados.
Observe que em todos os mtodos criamos uma instncia da classe DataContext identificada no nosso exemplo por NorthwindDataContext; Dim ctx As New NorthwindDataContext Aqui o banco de dados mapeado em um DataContext permitindo acesso a tabelas de forma transparente sem nos preocuparmos com conexo. O DataContext utiliza a interface IDbConnection do ADO.NET para acessar o armazenamento e pode ser inicializado tanto com um objeto de conexo ADO.NET estabelecido, ou com uma string de conexo que possa ser utilizada para criar a conexo. O DataContext o mecanismo usado para que seja feita a seleo no banco de dados, ficando responsvel por traduzir as selees e alteraes executando-as no banco de dados e transformando o resultado em objetos. A seguir, usamos consultas usando a sintaxe LINQ conforme abaixo:
Dim prod = (From p In ctx.Products Where p.ProductID = productID Select p).FirstOrDefault A consulta LINQ To SQL inicia com a clusula From e em seguida o operador de condio Where, depois ordenao com Order By e, no final, o operador de seleo Select. A clusula From a mais importante do LINQ To SQL, pois usada em todas as consultas. Uma consulta deve sempre comear com From (o Select pode estar implcito o From no). No exemplo, o mtodo SingeOrDefault retorna um nico e especfico elemento da sequncia de valores ou um valor padro se o elemento no for encontrado. No mtodo SalvarPedido, estamos incluindo um pedido na tabela Orders usando o mtodo InsertOnSubmit(). No mtodo SalvarPedido, aps definirmos valores para um novo pedido, estamos usando dois mtodos LINQ:
InsertOnSubmit() Este mtodo adiciona uma entidade , no caso a entidade novoPedido que do tipo Orders, em um estado pendente de incluso a tabela Orders; SubmitChanges() Este mtodo efetiva a incluso atual feita pelo InsertOnSubmit() na tabela do banco de dados. Deve ser chamado aps o mtodo InsertOnSubmit().
Quando SubmitChanges() invocado, o LINQ To SQL automaticamente gera e executa comandos SQL a fim de transmitir as alteraes de volta ao banco de dados. Voc pode, no entanto, sobrescrever este comportamento chamando uma stored procedure. Vejamos agora o tratamento dos eventos do controles do formulrio e as rotinas auxiliares. No evento Load do formulrio:
Private Sub FrmLINQ_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim NWDados As New NWContexto cboFuncionarios.DisplayMember = "FirstName" cboFuncionarios.ValueMember = "EmployeeID" For Each func In NWDados.GetFuncionarios cboFuncionarios.Items.Add(func) Next cboClientes.ValueMember = "CustomerID" cboClientes.DisplayMember = "CompanyName" For Each cli In NWDados.GetClientes cboClientes.Items.Add(cli) Next End Sub
No cdigo criamos uma instncia da classe NWContexto e usamos os mtodos GetFuncionarios e GetClientes. As rotinas AdicionarProduto(), AtualizaTotal() e LimpaTextBox() no sofreram alterao:
Private Sub AdicionarProduto() Dim LI As New ListViewItem LI.Text = txtID.Text LI.SubItems.Add(txtProduto.Text) LI.SubItems.Add(txtPreco.Text) LI.SubItems.Add(txtQtde.Text) LI.SubItems.Add(txtSubtotal.Text) ListView1.Items.Add(LI) AtualizaTotal() End Sub Private Dim Dim For Sub AtualizaTotal() items As Integer total As Decimal Each LI As ListViewItem In ListView1.Items
items += Integer.Parse(LI.SubItems(3).Text) total += Decimal.Parse(LI.SubItems(4).Text) Next txtItems.Text = items.ToString txtTotal.Text = total.ToString("#,###.00") End Sub Private Sub LimpaTextBox() txtID.Text = "" txtProduto.Text = "" txtPreco.Text = "" txtQtde.Text = "" txtSubtotal.Text = "" End Sub
Os eventos ColumnWidthChanged, KeyUp e SelectedIndexChanged do controle ListView tambm no sofreram alterao alguma:
Private Sub ListView1_ColumnWidthChanged(ByVal sender As Object, ByVal e As System.Windows.Forms.ColumnWidthChangedEventArgs) Handles ListView1.ColumnWidthChanged txtItems.Left = ListView1.Left + ListView1.Columns(0).Width + ListView1.Columns(1).Width + ListView1.Columns(2).Width txtItems.Width = ListView1.Columns(3).Width txtTotal.Left = txtItems.Left + txtItems.Width txtTotal.Width = ListView1.Columns(4).Width End Sub Private Sub ListView1_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles ListView1.KeyUp If e.KeyCode = Keys.Delete And ListView1.SelectedItems.Count > 0 Then ListView1.SelectedItems(0).Remove() AtualizaTotal() End If If e.KeyCode = Keys.Escape Then LimpaTextBox() txtID.Focus() End If End Sub Private Sub ListView1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListView1.SelectedIndexChanged ExibeDetalhe() End Sub
No evento KeyUp do controle TxtID onde logo aps o usurio digitar um cdigo de produto ao pressionar a tecla ENTER feita uma busca na tabela Products e so obtidos os dados do produto para exibio no formulrio. O cdigo deste evento foi alterado conforme abaixo:
Private Sub txtID_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles txtID.KeyUp If e.KeyCode = Keys.Enter Then If txtID.Text.Length > 0 Then Dim P As Product = (New NWContexto).GetProdutoPorID(txtID.Text.Trim) If P IsNot Nothing Then
Else
txtID.Clear() End If End If End If If e.KeyData = Keys.Down Then If ListView1.Items.Count > 0 Then LimpaTextBox() ListView1.Items(0).Selected = True ListView1.Focus() End If End If End Sub
Neste cdigo estamos usando o mtodo GetProdutoPorID() para obter o produto pelo cdigo informado usando uma instncia da classe DataContext. Agora vamos tratar o evento KeyUp do TextBox txtQtde de forma que aps informar a quantidade e pressionada a tecla ENTER, seja calculado o total e as informaes sejam exibidas no controle ListView configurando assim um novo pedido:
Private Sub txtQtde_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles txtQtde.KeyUp If e.KeyData = Keys.Enter Then Dim qty As Integer Integer.TryParse(txtQtde.Text, qty) If qty > 0 Then txtSubtotal.Text = (Decimal.Parse(txtPreco.Text) * qty).ToString("#,###.00") AdicionarProduto() LimpaTextBox() txtID.Focus() Else txtQtde.Text = "" End If End If If e.KeyData = Keys.Escape Then LimpaTextBox() txtID.Focus() End If End Sub
No evento Click do boto Salvar Pedido temos o cdigo que salvar o pedido e seus detalhes :
Private Sub btnSalvar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSalvar.Click If ListView1.Items.Count = 0 Then MsgBox("Inclua um ou mais itens para o pedido.") Exit Sub End If If cboClientes.SelectedIndex = -1 Then MsgBox("Selecione um cliente") Exit Sub End If If cboFuncionarios.SelectedIndex = -1 Then MsgBox("Selecione um funcionrio") Exit Sub End If Dim novoPedido As New Order novoPedido.CustomerID = CType(cboClientes.SelectedItem, Customer).CustomerID novoPedido.EmployeeID = CType(cboFuncionarios.SelectedItem, Employee).EmployeeID novoPedido.OrderDate = Today For Each LI As ListViewItem In ListView1.Items Dim novoDetalhe As New Order_Detail
Next
Dim ID As Integer ID = NWContexto.SalvarPedido(novoPedido) If ID > 0 Then MsgBox("Order " & novoPedido.OrderID.ToString & " submetido com sucesso...") Else MsgBox("Falha ao inserir um novo pedido no banco de dados") End If End Sub
No evento Click do boto Novo Pedido apenas limpamos as caixas de texto e colocamos o foco no controle txtID:
Private Sub btnNovo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNovo.Click LimpaTextBox() txtID.Focus() End Sub
Agora s alegria! Mas antes de prosseguir, vamos comparar o que mudou com a utilizao do LINQ to SQL em nosso projeto. Notou que no tivemos que utilizar instrues SQL para acessar e persistir informaes no banco de dados? otou tambm que no tivemos que nos preocupar com a definio de objetos connection, command, adapter, etc? A utilizao do LINQ to SQL abstraiu toda essa parte, permitindo um ganho de produtividade, pois o projeto ficou mais enxuto. Vamos executar o projeto e incluir um novo pedido. Aps informar os dados e clicar no boto Salvar Pedido teremos o seguinte resultado:
Dessa forma, neste projeto tivemos que definir as nossas classes de negcio para poder implementar a funcionalidade desejada e ao invs de fazer isso via cdigo usamos o LINQ to SQL para gerar as classes via mapeamento OR/M.