Desenvolvimento - ADO.NET

Usando componentes com ADO.NET

Neste artigo vou abordar o desenvolvimento de aplicações na plataforma .NET em diversos ambientes como Web Application, Windows Application e Mobile Application que consumirão componentes integrados com o ADO.NET.

por Renato Haddad



Neste artigo vou abordar o desenvolvimento de aplicações na plataforma .NET em diversos ambientes como Web Application, Windows Application e Mobile Application que consumirão componentes integrados com o ADO.NET.

A palavra chave é "Reaproveitamento de código", você deve ter visto muitas aplicações desenvolvidas que precisam fazer acesso a um banco de dados de diversos lugares, sendo que cada local contém a mesma rotina para acessar e retornar um DataSet. Até acho válido fazer desta forma se você não sabe como lidar com componentização, no entanto, a manutenção torna-se trabalhosa e insegura, por mais que você faça bem o copiar/colar.

Atualmente na plataforma .NET você precisa apenas de uma ferramenta para desenvolver o componente e criar todas as aplicações, é o Visual Sutio .NET. Quando você for instalar o componente criado, basta copiar no local de destino, ou seja, não existem mais os problemas de DLL Hell, conflitos com outras versões ou fabricantes de DLLs existentes.

Você já deve ter lido alguns artigos sobre desenvolvimento em N-tier (N-Camadas) onde é possível separar em 1, 2 ou 3 camadas. Nos exemplos apresentados aqui vou dividir as aplicações em apenas 2 camadas, sendo uma camada de acesso a dados que é o componente a ser desenvolvido e a camada de Interface que serão as aplicações Windows, Web e para um telefone celular.

Componente

O primeiro passo é criar o componente, o banco de dados a ser usado será o Northwind do SQL Server 2000 e as tabelas são Categories e Products. Abra o Visual Studio .NET e crie um novo projeto chamado clsDatabase do tipo Class Library, usando o Visual Basic .NET como linguagem.

Criação do Class Library

Figura 1: Criação do Class Library

Selecione o menu Project / Add Class para criar uma classe chamada clsAcessoDados.vb e digite o código seguinte que contém duas funções para acessar as respectivas tabelas.

Imports System.Data.SqlClient
Public Class clsAcessoDados
    Dim stringConn As String = "Initial Catalog=Northwind;Data Source=NomeDoServidor;User ID=sa"
Public Function Categorias() As DataSet
        Dim conn As SqlConnection
        Dim sql As String = "Select * FROM Categories ORDER BY CategoryName"
        Dim da As SqlDataAdapter
        Dim ds As DataSet
        conn = New SqlConnection(stringConn)
        conn.Open()
        da = New SqlDataAdapter(sql, conn)
        ds = New DataSet()
        da.Fill(ds, "categorias")
        Return ds
    End Function

    Public Function Produtos(ByVal idCategoria As Integer) As DataSet
        Dim conn As SqlConnection
        Dim sql As String
        Dim da As SqlDataAdapter
        Dim ds As DataSet
        sql = "Select ProductName, UnitPrice, UnitsInStock FROM Products "
        sql &= "WHERE CategoryID=" & idCategoria
        sql &= " ORDER BY ProductName"
        conn = New SqlConnection(stringConn)
        conn.Open()
        da = New SqlDataAdapter(sql, conn)
        ds = New DataSet()
        da.Fill(ds, "produtos")
        Return ds
    End Function
End Class

Note que a classe usada para acessar o SQL Server 2000 é a SqlClient, tornando mais rápido o acesso, pois é uma classe desenvolvida especificamente para acesso ao SQL Server 7 ou 2000. A função Categorias tem como objetivo selecionar todos os registros da tabela Categories, montar um DataAdapter chamado categorias e retornar um DataSet. Já a função Produtos tem como objetivo selecionar alguns campos da tabela Products onde o campo CategoryID seja igual ao parâmetro passado para função, em seguida monta um DataAdapter chamado produtos e retorna um DataSet. Como estas funções retornam um DataSet significa que independente da Interface a ser criada, o componente já está preparado para retornar os dados pesquisados, e como no .NET a forma de invocar e consumir um componente é transparente, você pode e deve usar isso em todas as chamadas dos controles que precisarem consumir estes dados. Após digitar o código, selecione o menu Build / Build Solution para compilar o componente. Dentro da pasta que você gravou o componente é criada uma pasta Bin com a DLL criada, e é justamente este arquivo que você deverá distribuir com a sua aplicação quando fizer o deployment.

Web Application

Uma aplicação feita para rodar na Internet é chamada de ASP.NET e a linguagem utilizada no nosso código será o Visual Basic .NET, mas nada o impede de utilizar o C# e consumir um componente feito em VB.NET ou o inverso também é válido. Crie um novo projeto chamado VSPJ do tipo ASP.NET Web Application e adicione um Web Form chamado consomeCompWeb.aspx contendo um ListBox chamado lstCategorias e um Datagrid chamado gridProdutos.

Estrutura dos controles nas páginas WEB

Figura 2: Estrutura dos controles nas páginas WEB

Para o controle lstCategorias, configure a propriedade AutoPostBack para True, pois toda vez que você selecionar uma categoria o código será disparado para preencher o Datagrid de produtos. Se o AutoPostBack estiver como False o código não será executado.

Para referenciar o componente criado selecione o menu Project / Add Reference, localize o respectivo arquivo clsDatabase.dll dentro da pasta Bin e clique no botão OK.

Referencie o componente a ser usado

Figura 3: Referencie o componente a ser usado

Digite o código para carregar as categorias assim que a página for aberta. O comando IsPostBack verifica se foi dado um Post na página, ou seja, esse código será carregado apenas na primeira vez que a página for carregada, mesmo estando no evento Page_Load.

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) 
Handles MyBase.Load
    If Not IsPostBack Then
       "referencia o componente
       Dim comp As New clsDatabase.clsAcessoDados()
       "atribui as propriedades para o ListBox
       With Me.lstCategorias
            .DataTextField = "CategoryName"
            .DataValueField = "CategoryID"
            "monta e popula o ListBox
            .DataSource = comp.Categorias.Tables("categorias").DefaultView
            .DataBind()
       End With
       Me.gridProdutos.Visible = False
    End If
End Sub

Explicação

Para referenciar um componente atribua o mesmo a uma variável e note que é utilizado o New NomeComponente.NomeClasse().

Dim comp As New clsDatabase.clsAcessoDados()

Para consumir a função existente na classe use a variável + ponto + nome da função. Como esta classe retorna um Dataset que contém um DataAdapter chamado categorias, então a origem (DataSource) deste ListBox é exatamente a tabela chamada categorias gerada pelo DataAdapter.

.DataSource = comp.Categorias.Tables("categorias").DefaultView

Digite o código no evento SelectedIndexChanged do ListBox lstCategorias para carregar o DataGrid com os produtos da respectiva categoria. Para facilitar, dê um duplo clique no lstCategorias que o evento é criado automaticamente.

Private Sub lstCategorias_SelectedIndexChanged
	(ByVal sender As System.Object, ByVal e As System.EventArgs)
	Handles lstCategorias.SelectedIndexChanged
    "referencia o componente
    Dim comp As New clsDatabase.clsAcessoDados()
    Me.gridProdutos.Visible = True
    "monta e popula o datagrid
    With Me.gridProdutos
        .DataSource = comp.Produtos(Me.lstCategorias.SelectedItem.Value).Tables("produtos")
        .DataBind()
    End With
End Sub

Preste atenção na origem (DataSource) do gridProdutos que contém o componente que invoca a função Produtos passando como parâmetro exatamente o código da categoria selecionada no lstCategorias. Esta função monta um DataAdapter chamado produtos que retorna o DataSet que será usado como origem do gridProdutos.

Defina esta página como padrão (Set As Start Page), salve o projeto, compile e execute no navegador (Ctrl + F5).

Execução da página WEB

Figura 4: Execução da página WEB

Veja a quantidade de código que a sua página contém, é significativamente menor se todos os códigos de acesso a dados estivessem sido inseridos aqui, fora que ainda vamos consumir o componente em outras aplicações. Com isso, qualquer manutenção fica muito simples, fácil e ágil de se realizar.Mobile Application

Para você criar uma aplicação para ser executada em um telefone celular, é preciso instalar o Mobile Internet Toolkit que é um SDK a ser utilizado pelo Visual Studio .NET. Neste exemplo, vamos consumir o mesmo componente existente que retorna um DataSet. Dentro da mesma aplicação ASP.NET criada, selecione o menu Project / Add New Item e adicione um novo projeto chamado MobileDatabaseComp.aspx do tipo Mobile Web Form contendo dois formulários com o controle ObjectList, respectivamente objCategorias e objProdutos.

Formulário para telefone celular

Figura 5: Formulário para telefone celular

Configure a propriedade LabelField do objCategorias para CategoryName e do objProdutos para ProductName. Insira o código para carregar as categorias no primeiro formulário. Note que o componente utilizado é o clsDatabase, ou seja, você não precisa criar todo o acesso a dados neste código porque isso já existe pronto no componente. Não reinvente a roda, planeje a aplicação para facilitar o desenvolvimento.

Private Sub Page_Load
(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim comp As New clsDatabase.clsAcessoDados()
    Me.objCategorias.DataSource = comp.Categorias.Tables("categorias").DefaultView
    Me.objCategorias.DataBind()
End Sub

Salve e execute no simulador do telefone celular (Microsoft Mobile Emulator 3.0). Caso você não tenha um simulador é possível rodar o código no navegador. Isso é fantástico porque o próprio Framework já reconhece qual o dispositivo que invocou a página e montar exatamente com o que ele suporta.

Execução da página no telefone celula

Figura 6: Execução da página no telefone celula

Quando você selecionar alguma categoria é executado o código que pesquisa todos os produtos e exibe no objProdutos.

Produtos da categoria selecionada

Figura 7: Produtos da categoria selecionada

O próprio ObjectList é um controle inteligente que atribui um link ao item selecionado para poder exibir em outra página o restante das informações do produto.

Todas as informações do produto selecionado

Figura 8: Todas as informações do produto selecionado

Windows Application

Que tal utilizar os componentes em uma aplicação Windows? Esse é o objetivo deste exercício, reutilizar o máximo possível os códigos existentes. Abra o Visual Studio .NET e crie um projeto do tipo Windows Application chamado consomeCompWin com os seguintes controles: um ComboBox, um ListBox e um DataGrid, nomeados dropCategorias, lstProdutos e gridProdutos respectivamente.

Crie um código no evento Load do formulário para carregar o ComboBox de categorias. Veja que existe um tratamento de erro para a conexão com o componente, então como exercício insira nos códigos anteriores outras rotinas de tratamento de erros.

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Handles MyBase.Load
    Dim comp As New clsDatabase.clsAcessoDados()
    Try
        Me.dropCategorias.DataSource = comp.Categorias.Tables("categorias").DefaultView
        Me.dropCategorias.DisplayMember = "CategoryName"
        Me.dropCategorias.ValueMember = "CategoryID"
    Catch myErr As System.Exception
        MessageBox.Show(myErr.ToString, "Alerts", MessageBoxButtons.OK)
    End Try
End Sub
Após selecionar uma categoria no ComboBox é preciso invocar o componente para popular o ListBox lstProdutos e o DataGrid gridProdutos.
Private Sub dropCategorias_SelectedIndexChanged
(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles dropCategorias.SelectedIndexChanged
    Dim comp As New clsDatabase.clsAcessoDados()
    Try
        "captura a categoria selecionada
        Dim catIndex As Integer = Me.dropCategorias.SelectedIndex
        Dim catSelected As Integer = Me.dropCategorias.Items(catIndex)!CategoryID
        "monta o ListBox dos produtos
        Me.lstProdutos.DataSource = comp.Produtos(catSelected).Tables("produtos").DefaultView
        Me.lstProdutos.DisplayMember = "ProductName"
        "monta o DataGrid dos produtos
        Me.gridProdutos.DataSource = comp.Produtos(catSelected).Tables("produtos").DefaultView
    Catch myErr As System.Exception
        MessageBox.Show(myErr.ToString, "Alerts", MessageBoxButtons.OK)
    End Try
End Sub

Após selecionar uma categoria no ComboBox é preciso invocar o componente para popular o ListBox lstProdutos e o DataGrid gridProdutos.

Salve e execute a aplicação.

Execução da aplicação Windows Form

Figura 9: Execução da aplicação Windows Form

Conclusão

Desenvolver uma aplicação bem estruturada proporcionando o uso de componentes é uma excelente maneira de você e a sua equipe trabalhar de forma organizada, modular, simples e objetiva. Procure planejar toda a aplicação antes de desenvolvê-la e veja as facilidades e as implicações de distribuir em camadas. Toda e qualquer manutenção a ser feita sempre será mais rápida. "No stress, think .NET"

Renato Haddad

Renato Haddad - MVP, MCPD e MCTS, palestrante em eventos da Microsoft em diversos países, ministra treinamentos focados em produtividade com o VS.NET 2008, ASP.NET 3.5, Reporting Services e Windows Mobile.