![]() |
||||||||
|
|
||||||||


| com exemplos em VB |
| Componente para deixar forms em Vb semelhantes às telas do winnamp |
| Componente para colocar sua aplicação VB no Systray |
| Componente para transformar sua aplicação VB em serviço |
| Ferramentas úteis para quem usa Olap Server |
| |

|
||||||||||||||||
Pesquisa personalizada
Criando uma camada de dados com o .NET 2.0 Anteriormente falamos sobre a criação de uma camada de dados no artigo em http://www.bufaloinfo.com.br/artigos/artigo281104.asp . O que explicamos neste artigo continua válido para o .NET 2.0, com mudanças mínimas. Assim sendo esta forma que apresentamos anteriormente ainda é válida, mas as mudanças existentes no .NET 2.0 fizeram com que esta não seja sempre a melhor opção. No .NET 2.0 temos um volume maior de recursos para aumentar a produtividade na interface. Entre esses recursos temos o ObjectDataSource, que permite fazermos um vinculo de dados entre a interface e um objeto, tudo feito de forma visual. Neste ponto começam nossos problemas. Os componentes de negócio produzidos pela metodologia anterior não se encaixam com o ObjectDataSource, o que faz com que tenhamos que dispensar alguns dos novos recursos que geram alta produtividade no .NET 2.0. Mas temos alternativas, é disso que vamos tratar neste artigo. Vamos criar uma camada de negócios e dados utilizando o .NET 2.0 e vamos compara-la com o que criamos anteriormente no .NET 1.1 Primeira etapa : Criando uma camada de acesso a dados simples Crie um novo webSite Adicione um novo projeto do tipo ClassLibrary, vamos chama-lo de libDados Na libDados, utilize o add new item para adicionar um novo dataset chamado dsProdutos Pela ToolBox, adicione um novo TableAdapter Utilize a seguinte query para montar o TableAdapter :
Nas advanced options, desmarque a opção optimistic concurrency.
Na tela para escolha dos métodos a serem gerados, deixe as opções default marcadas.
Clique com o botão direito sobre o Fill do TableAdapter e selecione a opção Add Query
Selecione o tipo de query como "Update"
Altere a query de Update, mudando o parâmetro de @Original_productId para @ProductID
No site web, crie uma referência para o projeto libDados
Adicione um ObjectDataSource na página default.aspx Configure o objectDataSource, apontando para o TableAdapter
Altere o método de Update para o nosso método Atualizar
Nas propriedades do objectDataSource, altere a propriedade OldValuesParametersFormatString deixando apenas como "{0}" Adicione uma dataGrid, vincule-a ao ObjectDataSource e teste, incluindo a edição na grid.
Resultado : Neste ponto temos a interface da aplicação fazendo todo o acesso a dados através de um componente, o tableAdapter, sem acesso direto ao banco. Uma das muitas questões que ficam pendentes é se essa estrutura nos trará os benefícios de manutenção que temos como objetivo ao utilizar uma estrutura em camadas. Na sequencia de exemplos a seguir vamos responder a esta pergunta. Segunda Etapa : Criando um método personalizado Vamos criar em nossa aplicação o recurso de atualizar o preço dos produtos com base em um percentual informado e vamos fazer isso através de nosso objeto de negócios. Crie uma nova query no tableAdapter Defina o tipo da query como de Update Utilize a seguinte query de Update :
Defina o nome do método como AtualizarPreco
Na página, adicione um novo ObjectDataSource Configure o ObjectDataSource apontando para nosso TableAdapter Selecione como método de Update o nosso AtualizarPreco Insira uma textbox e um botão na página
Chamaremos a textbox de txtPercentual e o botão de cmdAtualizarPreco. Você pode também inserir um requiredFieldValidator. Configure a propriedade UpdateParameters do ObjectDataSource, aponte para a textbox.
Programe o click do botão da seguinte forma : 39 Protected Sub cmdAtualizarPreco_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdAtualizarPreco.Click 40 41 ObjectDataSource2.Update() 42 GridView1.DataBind() 43 44 End Sub
Terceira Etapa : Implementando uma regra de negócio personalizada Vamos implementar uma regra de validação personalizada para o percentual de aumento. Será uma regra simples, mas demonstrará como regras diversas podem ser implementadas com o TableAdapter Utilize o Add New Item e adicione uma nova classe Troque o nome da classe para ProductsTableAdapter Crie o nameSpace dsProdutosTableAdapters e deixe a classe dentro deste nameSpace
No TableAdapter, altere a propriedade Modifiers de nosso método AtualizarPreco para Private
Altere o nome do método de AtualizarPreco para privAtualizarPreco
Crie um novo método AtualizarPreco com a mesma assinatura e com a seguinte implementação : 46 Public Sub AtualizarPreco(ByVal Percentual As Decimal) 47 48 If Percentual > 50 Then 49 Throw New ApplicationException("Percentual muito alto") 50 End If 51 52 Me.privAtualizarPreco(Percentual) 53 54 End Sub
No client, apenas para deixar a interface agradável, vamos adicionar um tratamento de erro na atualização : 56 Protected Sub cmdAtualizarPreco_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdAtualizarPreco.Click 57 58 Try 59 ObjectDataSource2.Update() 60 Catch ex As Exception 61 Me.ClientScript.RegisterClientScriptBlock(Me.GetType(), "xxx", "alert('" & ex.Message & "')", True) 62 63 End Try 64 GridView1.DataBind() 65 66 End Sub Com isso adicionamos uma nova regra de negócio e obtivemos exatamente o que se espera de um desenvolvimento em camadas : Facilidade de manutenção. Foi possível adicionar esta regra sem que a interface client tivesse que ser alterada.
Quarta Etapa : Implementando regras nos métodos padrões Quando criamos o TableAdapter foram criados os métodos Fill e GetData. Junto desses métodos, foram criados métodos de atualização (insert/update/delete), sendo que nos exemplos anteriores chegamos a substituir o método de update por um método nosso, personalizado. A questão é como fazer para implementar regras de negócio nestes métodos. Assim como alteramos o modifers de nosso método personalizado, no exemplo anterior, poderiamos fazer o mesmo com estes métodos. Mas existe um problema : Junto ao Fill e GetData, só podemos alterar o modifier dos dois, Fill e GetData. Não podemos alterar o Modifier dos métodos de atualização que foram gerados junto do Fill e GetData. Nesse caso o melhor é adotarmos um padrão : Não utilizar os métodos de atualização criados junto com o Fill/GetData e sim criar nossas próprias querys de atualização a parte. Então, durante o wizard para criação do Fill, desmarcamos a opção GenerateDbDirectMethods.
Com isso podemos criar nossas próprias querys de atualização (utilizando o Add Query) e implementar regras de negócio da mesma forma que fizemos nos exemplos anteriores. Quinta Etapa : Preparando o componente para uso em aplicações windows As aplicações windows possuem uma importante diferença em relação a aplicações web que precisa ser considerada para a montagem deste componente : Enquanto as aplicações web atualizam registros individualmente, as aplicações windows atualizam (e aqui falo de insert/update/delete) blocos de registros utilizando o dataSet. O TableAdapter possui diferentes métodos de atualização exatamente prevendo as diferentes formas de atualização entre aplicações web e windows. Para aplicações web o TableAdapter possui os DbDirectMethods, enquanto que para aplicações Windows o TableAdapter gera métodos de update que recebem como parâmetro a DataTable ou DataSet e fazem a atualização de todos os dados no banco. São 2 métodos de Update em overloads. Esses métodos, porém, nos causarão problema : Não temos o controle do modifers destes métodos, pois são gerados juntamente com o Fill/GetData. Também não temos uma forma direta de "desligar" a geração destes métodos, como fizemos com os DbDirectMethods. É importante lembrar neste ponto que o TableAdapter mantém um DataAdapter - o mesmo dataAdapter que utilizávamos na versão 1.1 - configurado com as querys que serão executadas no banco. A solução para "desligar" a geração dos métodos de atualização para o ambiente windows é desligando a geração do insert/update/delete nas advanded options da geração do método Fill. O problema é que isso desliga também a configuração do DataAdapter interno para a realização de atualizações na base.
Nesse caso somos obrigados a criar não só o método de atualização, mas um método que faça a configuração do DataAdapter com as querys de atualização. Para isso podemos utilizar nosso velho amigo CommandBuilder, que na versão 2.0 aprendeu alguns truques novos. Veja como fica o código em nosso productsTableAdapter : 68 Public Sub AtualizarProdutos(ByVal dados As dsProdutos.ProductsDataTable) 69 70 InicializarAdapter() 71 Me._adapter.Update(dados) 72 End Sub 73 74 75 Private Sub InicializarAdapter() 76 Dim cb As SqlClient.SqlCommandBuilder 77 78 Me._adapter.SelectCommand = Me.CommandCollection(0) 79 80 cb = New SqlClient.SqlCommandBuilder(Me._adapter) 81 cb.ConflictOption = ConflictOption.CompareAllSearchableValues 82 83 Me._adapter.DeleteCommand = cb.GetDeleteCommand 84 Me._adapter.UpdateCommand = cb.GetUpdateCommand 85 Me._adapter.InsertCommand = cb.GetInsertCommand 86 End Sub No inicializarAdapter utilizamos o commandBuilder para fazer a configuração do dataAdapter, enquanto que no AtualizarProdutos tomamos o cuidado de chamar o inicializarAdapter antes de fazer a atualização. A variável "_adapter" é private, mas nós estamos fazendo uma partial class, portanto ela ainda encontra-se dentro do escopo. Observe a propriedade ConflictOption, no CommandBuilder. Na versão anterior a forma de tratamento de conflitos não era configurável, isso mudou na versão 2.0, com essa propriedade. Neste exemplo está sendo determinado que a clausula where das instruções update e delete contenham todos os campos, de forma que se houverem atualizações simultâneas os registros não sejam sobrescritos, não havendo perda de dados. No método AtualizarProdutos podemos ainda implementar outros recursos com relação a gravação, tal como gravação transacional, controle de campos auto-numeração, etc. Veja em http://www.bufaloinfo.com.br/dicas.asp?cod=611 , http://www.bufaloinfo.com.br/dicas.asp?cod=630 e http://www.bufaloinfo.com.br/dicas.asp?cod=657 Sexta Etapa : Criando a aplicação Windows Adicione na solução um novo projeto Windows Defina este projeto como startUp Project
Adicione uma referência para a libDados Abra a janela de Data Sources em Data->Show Data Sources
Adicione um novo data source No tipo, escolha "Object"
Na seleção de objetos, aponte para o dsProducts na libDados
Arraste a tabela Products que apareceu na janela Data Sources para dentro do formulário
Clique com o botão direito no ProductsBindNavigator e selecione "Edit Items"
Habilite o botão SaveItem
Codifique o form_load para carregar os dados para o dataSet 88 Dim obj As New libDados.dsProdutosTableAdapters.productsTableAdapter 89 90 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 91 92 obj.Fill(DsProdutos.Products) 93 End Sub Com um duplo clique no botão salvar, que encontra-se no topo do formulário, codifique a gravação dos dados : 96 Private Sub ProductsBindingNavigatorSaveItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ProductsBindingNavigatorSaveItem.Click 97 98 ProductsBindingSource.EndEdit() 99 obj.AtualizarProdutos(DsProdutos.Products) 100 MsgBox("Todos os produtos foram atualizados") 101 End Sub Observe o uso do EndEdit para garantir a gravação do registro atual, caso ele esteja em edição. Sétima Etapa : Implementando regras de negócio para o ambiente Windows e Web O grande desafio da implementação de regras é evitar que o código dessas regras seja duplicado. No ambiente web, utilizamos os métodos de atualização direta, recebendo cada campo como um parâmetro. No ambiente windows, recebemos uma dataTable que pode conter diversos registros. Formatos diferentes de dados. Portanto nosso desafio é validar ambos sem duplicar a lógica de validação. Precisaremos então ter um método privado de validação de dados. Este método privado de validação será chamado tanto da atualização direta como da atualização com dataTables. Porém na implementação temos que escolher uma entre duas opções :
Assim sendo, em um dos casos precisa haver uma conversão do formato dos dados. Veja um exemplo a seguir. Neste caso convertemos os dados do dataSet, chamando a validação linha a linha : 104 Private Sub ValidarDados(ByVal productName As String, ByVal unitPrice As Decimal, ByVal UnitsInStock As Integer, ByVal ProductId As Integer) 105 106 If unitPrice > 1000 Then 107 Throw New ApplicationException("O preço é muito alto") 108 End If 109 End Sub 110 111 Public Sub AtualizarProdutos(ByVal dados As dsProdutos.ProductsDataTable) 112 InicializarAdapter() 113 114 Dim dt As DataTable 115 dt = dados.GetChanges() 116 117 For Each dr As dsProdutos.ProductsRow In dt.Rows 118 ValidarDados(dr.ProductName, dr.ProductID, dr.UnitsInStock, dr.ProductID) 119 120 Next 121 122 Me._adapter.Update(dados) 123 End Sub 124 125 Public Sub InserirDados(ByVal productid As Integer, ByVal productName As String, ByVal unitPrice As Decimal, ByVal unitsInStock As Integer) 126 127 Me.ValidarDados(productName, unitPrice, unitsInStock, productid) 128 129 Me.privInserirDados(productid, productName, unitPrice, unitsInStock) 130 131 End Sub Conclusões finais
Como você pode observar neste quadro comparativo, o modelo que criamos para a versão 1.1 tem várias vantagens em relação ao novo modelo que acabei de apresentar. Mas a única desvantagem pode ser decisiva : o modelo anterior não se integra com a nova interface gráfica, enquanto que o novo evita até mesmo boa parte da codificação nas camadas de componentes. Boa parte das aplicações no .NET 2.0 podem ser produzidas neste novo modelo com vantagens para a produtividade e manutenção. Certamente apenas algumas, as maiores e com necessidades específicas, precisarão utilizar os recursos mais versáteis do modelo anterior.
Dennes Torres |
||||||||||||||||
|
Veja abaixo os comentários já enviados :
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: Quer
saber mais?
Faça um curso na Búfalo Informática, Treinamento e Consultoria e Prepare-se para o Mercado! Veja o que a Búfalo tem para você. |
||||||||||||||||
© Búfalo Informática,
Treinamento e Consultoria -
Rua Álvaro Alvim, 37 Sala 920 - Cinelândia - Rio de Janeiro / RJ
Tel.: (21)2262-1368 (11) 3170-3056 e-Mail: contato@bufaloinfo.com.br