VB.NET - Criando uma aplicação em camadas (MVC)
No artigo - Padrões de Projeto : O modelo MVC - Model View Controller - falei sobre os padrões de projeto , mais especificamente do modelo MVC. Vou mostrar neste artigo um exemplo prático de como podemos criar uma aplicação em 3 camadas , bem próxima do modelo MVC , usando o VB.NET.
Nota: Embora esteja me referindo aqui ao padrão MVC, não estamos implementando realmente esse padrão, mas apenas no baseado no conceito da separação de camadas para implementar uma aplicação em camadas.
Vou criar um projeto do tipo VB.NET com um formulário e um datagrid usando o acesso a dados via DataSet para criar uma aplicação em 3 camadas que permita acessar , alterar e atualizar os dados usando o DataGrid e refletir isto em um DataSet que representa a tabela Customer do banco de dados Northwind.mdb.
O código irá mostrar como enviar novas linhas (registros) , alterar linhas e excluir linhas usando uma camada de serviços que atualiza o banco de dados usando um DataSet. Iremos dividir logicamente nosso projeto em 3 partes :
A aplicação que irei desenvolver pode ser dividido em dois projetos distintos :
A camada de apresentação - Windows Forms
Vamos começar com a camada de apresentação. Abaixo temos o formulário do projeto com os seguintes componentes:
- 1 DataGrid - grdData - 3 Buttons - Button1 , Button2 e Button3 O componente DataGrid irá exibir os dados ao usuário e os botões irão ter as seguintes funcionalidades :
Por que estou usando um DataGrid ? Bem... O DataGrid é um controle de Servidor que pode ser facilmente manipulado para renderizar um conjunto de registros pela vinculação com um DataSet. |
Você deve estar meio desconfiado e deve também estar duvidando que é possível criar uma aplicação 3 camadas da forma com eu estou fazendo. Com certeza ao ler que eu vou vincular o DataSet ao DataGrid você pode até pensar que a vinculação será feita feita como nos velhos tempos do VB6.
Calma !!! No mundo .NET vincular tem um sentido muito diferente. Quando um DataSet é vinculado a um DataGrid , os dados do DataSet são copiados para o DataGrid. As alterações feitas nos dados do DataGrid são então repassadas para o DataSet para refletir as mundaças. Qual a diferença ??? Vou explicar ...
Quando você usava o VB6 e a ADO (lembra ???) as técnicas de vinculação de dados envolviam vincular os dados do Grid diretamente a um controle Data e dai para o banco de dados. Neste esquema a conexão com o banco de dados fica aberta o que limita muito nossa aplicação pois você tem a camada de apresentação diretamente ligada com a camada de dados.
Com o VB .NET temos o grid ainda vinculado ao DataSet , mas o DataSet não tem uma conexão com o banco de dados. Na verdade o DataSet nem mesmo sabe ou se importa em saber de onde os dados estão vindo. O DataSet pode ser preenchido com dados a partir de uma variedade de fonte de dados e até mesmo se preenchido manualmente sem fonte de dados alguma. Ai que esta a diferença...
Quando o usuário altera os dados no DataGrid do formulário, as mudanças são enviadas ao DataSet de forma automática. Qualquer nova linha de registro incluída é também incluída no DataSet e qualquer linha alterada é atualizada no DataSet. Linhas excluídas do DataGrid são removidas do DataSet (elas são marcadas como excluídas).
O DataSet trata todas as mudanças nos dados armazenando o valor original e atual de cada linha e coluna. Assim , se um DataGrid contiver 1000 linhas de dados e o usuário alterar 3 linhas, incluir 1 nova linha e excluir outras 2 linhas, as linhas afetadas podem ser extraíadas do DataSet vinculado para outro DataSet de maneira que o novo DataSet irá conter somente estas 6 linhas alteradas.
A seguir o código da classe frmMain : Aqui temos a classe frmMain onde a variável m_oDS representa o DataSet.
Public Class frmMainInherits System.Windows.Forms.Form '//---------------------------------------------------------------------------------------------------- '// Declara variável de class '//---------------------------------------------------------------------------------------------------- Private m_oDS As DataSet
'//---------------------------------------------------------------------------------------------------- '// Retorna e carrega os dados para o formulário '//---------------------------------------------------------------------------------------------------- Private Sub LoadData()Dim oCustomer As BusinessServices.Customer = New BusinessServices.Customer() grdData.DataBindings.Clear() m_oDS = oCustomer.GetData() grdData.DataSource = m_oDS.Tables("Customer") oCustomer = Nothing End Sub '//------------------------------------------------------------------------------------------------------------ '// Envia os dados alterados para os serviços de negócios '//------------------------------------------------------------------------------------------------------------ Private Sub SaveData()
Dim lRetVal As Long Dim oCustomer As BusinessServices.Customer = New BusinessServices.Customer()Dim oDS_Delta As DataSet Dim sMsg As String '//--- Verifica se houve alterações If m_oDS Is Nothing Then Exit SubIf Not m_oDS.HasChanges() Then Exit Sub '//--- Trata todas as mudanças oDS_Alterados = m_oDS.GetChanges() sMsg = "Esta certo que quer salvar " & oDS_Alterados.Tables(0).Rows.Count() & " linhas da fonte de dados ? " lRetVal = MsgBox(sMsg, Microsoft.VisualBasic.MsgBoxStyle.Question + Microsoft.VisualBasic.MsgBoxStyle.YesNo, "Salva Dados") Select Case lRetVal Case vbYes Try '//--- Salva todas as alterações sMsg = oCustomer.SaveData(oDS_Alterados) LoadData() Catch e As Exception sMsg = "Erro ao salvar dados." & vbCrLf & vbCrLf & e.Message.ToString() Finally MsgBox(sMsg, Microsoft.VisualBasic.MsgBoxStyle.Information, "Salva Dados") End Try Case vbNo '//--- Nada End Select oDS_Delta = Nothing oCustomer = Nothing End SubPrivate Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click LoadData() End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click SaveData() End Sub Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click Me.Dispose() End Sub
End Class |
- Quando o usuário clicar no botão - Carregar Dados - o método LoadData() será invocado . Nele estamos declarando e criando uma instância da classe serviços de negócios :
Dim oCustomer As BusinessServices.Customer = New BusinessServices.Customer()
- A seguir declaramos a vinculação de dados e iniciamos com o status clear (limpo). Então usamos o método GetData do objeto de serviços de negócios - oCustomer - para retornar o DataSet preenchido com os dados da tabela - Customer - para o formulário através do DataGrid. Feito isto o DataSet será local e estará vinculado ao DataGrid.
grdData.DataBindings.Clear()
m_oDS = oCustomer.GetData()
grdData.DataSource = m_oDS.Tables("Customer")
oCustomer = Nothing
- Com os dados preenchendo o DataGrid e sendo exibidos no formulário o usuário poderá interagir com os dados via interface : alterando , excluindo e incluindo novos registros. Para salvar as alterações o usuário irá clicar no botão - Salvar Dados - que irá invocar o método SaveData().
- O método SaveData() cria uma instância dos objetos de serviços - BusinessServices.Customer() - e verifica se houve qualquer alteração nos dados usando o método HasChanges(). Como o DataSet esta vinculado ao DataGrid qualquer alteração feita será refletida no DataSet. Havendo alterações eu utilizo a variável oDS_Alterados para armazenar os registros alterados : oDS_Alterados = m_oDS.GetChanges()
- O método GetChanges do DataSet copia as linhas alteradas do DataSet e as coloca em um novo DataSet: oDS_Alterados.
- Finalmente o usuário deverá confirmar se deseja salvar as alterações
A camada de serviços
A camada de serviços é definida em uma classe chamada : BusinessServices. O código da classe esta descrito a seguir :
'//-------------------------------------------------------------------------------------------------------- '// Declara todos os NameSpaces que serão referenciados '//-------------------------------------------------------------------------------------------------------- Imports SystemImports System.DataImports System.Data.OleDb'//-------------------------------------------------------------------------------------------------------------- '// NameSpace BusinessServices '//-------------------------------------------------------------------------------------------------------------- Namespace BusinessServicesPublic Class Customer
'//---------------------------------------------------------------------------------------------------- '// Declara as variáveis de Classe '//---------------------------------------------------------------------------------------------------- Private m_sProvider As String = "PROVIDER=Microsoft.Jet.OLEDB.4.0;"Private m_sServer As String = "DATA SOURCE=C:/teste/" ' Private m_sDatabase As String = "Northwind1.mdb" Private m_oDS As DataSet Private m_oCn As OleDbConnection Private m_oDA As OleDbDataAdapter Private m_sClassName As String = "Customer" '//--- o nome da classe '//---------------------------------------------------------------------------------------------------- '// Constructor (sem argumentos) '//---------------------------------------------------------------------------------------------------- Sub New()Dim sSQL As String = "" Dim oSelCmd As OleDbCommand Dim oInsCmd As OleDbCommand Dim oUpdCmd As OleDbCommand Dim oDelCmd As OleDbCommand '--------------------------------------------------------- '--- define a conexao '---------------------------------------------------------InitializeConnection() '--------------------------------------------------------- '--- define o SELECT Command '---------------------------------------------------------sSQL = "SELECT CustomerID, CompanyName, ContactName, City, Region FROM Customers ORDER BY CompanyName "
oSelCmd = Nothing oSelCmd = New OleDbCommand(sSQL, m_oCn) oSelCmd.CommandType = CommandType.Text '--------------------------------------------------------- '--- define o UPDATE Command '---------------------------------------------------------sSQL = "UPDATE Customers " & _ " SET CompanyName = @CompanyName , ContactName = @ContactName, City = @City, Region = @Region WHERE CustomerID = @CustomerID "
oUpdCmd = Nothing oUpdCmd = New OleDbCommand(sSQL, m_oCn)
With oUpdCmd .CommandType = CommandType.Text With .Parameters .Add(New OleDbParameter("@CompanyName", OleDbType.VarChar, 40, "CompanyName")) .Add(New OleDbParameter("@ContactName", OleDbType.VarChar, 30, "ContactName")) .Add(New OleDbParameter("@City", OleDbType.VarChar, 15, "City")) .Add(New OleDbParameter("@Region", OleDbType.VarChar, 15, "Region")) .Add(New OleDbParameter("@CustomerID", OleDbType.LongVarChar, 5, "CustomerID")) End With End With '--------------------------------------------------------- '--- define o INSERT Command '---------------------------------------------------------sSQL = "INSERT INTO Customers " & _ " (CompanyName, ContactName, City, Region, CustomerID) VALUES (@CompanyName, @ContactName, @City, @Region, @CustomerID)" oInsCmd = Nothing oInsCmd = New OleDbCommand(sSQL, m_oCn)
With oInsCmd .CommandType = CommandType.Text With .Parameters .Add(New OleDbParameter("@CompanyName", OleDbType.VarChar, 40, "CompanyName")) .Add(New OleDbParameter("@ContactName", OleDbType.VarChar, 30, "ContactName")) .Add(New OleDbParameter("@City", OleDbType.VarChar, 15, "City")) .Add(New OleDbParameter("@Region", OleDbType.VarChar, 15, "Region")) .Add(New OleDbParameter("@CustomerID", OleDbType.LongVarChar, 5, "CustomerID")) End With End With '--------------------------------------------------------- '--- define o DELETE Command '---------------------------------------------------------sSQL = "DELETE Customers WHERE CustomerID = @CustomerID " oDelCmd = Nothing oDelCmd = New OleDbCommand(sSQL, m_oCn) With oDelCmd .CommandType = CommandType.Text With .Parameters .Add(New OleDbParameter("@CustomerID", OleDbType.LongVarChar, 5, "CustomerID")) End With End With '--------------------------------------------------------- '--- cria e define os comandos para o DataSet '---------------------------------------------------------m_oDA = New OleDbDataAdapter() With m_oDA .SelectCommand = oSelCmd .UpdateCommand = oUpdCmd .DeleteCommand = oDelCmd .InsertCommand = oInsCmd End With '//--- Destroi o objeto connectionm_oCn = Nothing End Sub '//------------------------------------------------------------------------------------------------------------ Public Function SaveData(ByVal oDS As DataSet) As StringDim sMsg As String Dim lRecsAffected As Long Dim oTran As OleDb.OleDbTransaction '--------------------------------------------------------- '//--- Salva os dados '--------------------------------------------------------- Try '--- define a conexaoInitializeConnection() m_oCn.Open() '--- inicia a transacao oTran = m_oCn.BeginTransaction() '--- atualiza o banco de dados lRecsAffected = m_oDA.Update(oDS, m_sClassName) '--- consolida (commit) as mudanças oTran.Commit() '--- define as mensagens para o usuario sMsg = lRecsAffected & " registros foram atualizados" Catch e As Exception '--- Ocorreu um erro Desfaz a transacao oTran.Rollback() sMsg = "Os registros não foram atualizados." & vbCrLf & e.Message.ToString() Finally '--- Fecha a conexaooTran = Nothing m_oCn.Close() m_oCn = Nothing SaveData = sMsg End Try End Function '//------------------------------------------------------------------------------------------------------------// retorna os dados da tabela clientes '//------------------------------------------------------------------------------------------------------------ Public Function GetData() As DataSet'--- Cria um novo datase m_oDS = New DataSet() '--- preenche o dataset com os dados dos clientes m_oDA.Fill(m_oDS, m_sClassName) '//--- Retorna o dataset Return m_oDS End Function '//------------------------------------------------------------------------------------------------------------ '// Inicializa a conexão '//------------------------------------------------------------------------------------------------------------ Private Sub InitializeConnection()'--- define a conexao m_oCn = New OleDbConnection(m_sProvider & m_sServer & m_sDatabase) End Sub End Class End Namespace
|
A camada de acesso a dados vai ser discutida em outros artigos sobre o tema mas creio que deu para dar uma visão geral sobre o assunto.
Aguarde mais artigos sobre o tema em breve ...
Eu sei é apenas VB .NET mas eu gosto:
Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#