Introdução
Convergência e Mobilidade. Aí estão duas palavras que vem se tornando o foco do mercado de tecnologia no Brasil e no mundo. Basta ver os números. Segundo o IDC(IDC's Enterprise Mobility & Convergence São Paulo) 70% de um universo de 90 empresas pretendem contratar uma integradora de soluções móveis em 2008. O presidente da Acel (Associação Nacional das Operadoras de Celular), Ércio Zilli, recentemente disse que, no próximo ano, o crescimento da telefonia móvel deverá ser entre 10% e 12%. Estamos realmente entrando na quinta era da computação, onde, os antes poderosos e solitários desktops, começam a se integrar, formando complexas e robustas estruturas de informação distribuída com pontos móveis.
As pessoas, hoje, perdem pouco a pouco a idéia do “computador de mesa”, ao passo que as sociedades virtuais juntamente com a grande enciclopédia INTERNET, começam a se tornar uma realidade estabelecida. E para a integração dos indivíduos e seus respectivos personagens neste novo mundo rpgístico, é necessário que os aparelhos móveis sejam utilizados. Fator como este, transforma o mercado de desenvolvimento em um grande funil que converge para o projeto de software móvel. Como no início da história da engenharia da computação, é cobrado agora do desenvolvedor de sistemas o skill criatividade. Pouco espaço, pouca memória, muita objetividade, muita versatilidade.
Neste contexto, o presente artigo apresenta um tutorial que ensina passo-a-passo, como construir um framework para acesso a dados na versão compacta e móvel do Microsoft SQL Server. O SQL Server Compact Edition é um SGBD suportado pelos sistemas operacionais da linha Windows Mobile. Este banco de dados oferece muitos recursos, do ponto de vista de ser móvel. Permite a criação e manipulação de dados em bases através de uma simples interface. Nele, podem-se criar tabelas, inserir registros, inserir colunas, definir chaves primárias, auto-incremento, transações e campos dos mais variados tipos, incluindo imagens e binários. Suporta consultas do tipo SQL e dispõe de até dois gigabytes de espaço para armazenamento. Vamos acompanhar nas próximas seções como implementar esse sistema em nossos projetos e como utiliza-lo através de uma camada de acesso.
Uma camada para acesso a dados
Nosso framework de acesso vai trabalhar numa camada separada do projeto (Figura 1). Vamos definir toda a lógica que corresponde a manipulação de dados dentro de uma classe separada. No final do projeto, essa classe vai ser compilada e um arquivo de extensão DLL será gerado. Este arquivo pode ser reutilizado sempre que necessário em outros projetos. A classe, por sua vez, pode ser expandida, suportando um maior número de bancos de dados. Empregaremos assim, os alicerces de encapsulamento e abstração que a Programação Orientada a Objetos dispõe.
Nesta classe serão definidos métodos que acessam o banco de dados para retornar informações ou modifica-las. Criaremos ainda alguns métodos mais específicos como os que criam base de dados em tempo de execução e os que trabalham com transações. Bem, então vamos por a mão na massa...
Iniciando o projeto
Para a construção do nosso projeto utilizaremos o Visual Studio 2005 e a linguagem VB.NET 2005 num projeto de Windows Mobile 5.0 Pocket PC Application. Para isso, abra o VS2005, vá ao menu File>New Project. Quando a janela New Project for apresentada, escolha na árvore de projetos a opção Visual Basic Projects>Smart Device>Windows Mobile 5.0 Pocket PC. Em seguida nos tipos de projeto apresentados selecione Device Application e dê o nome de AcessoDados. Clique em OK para confirmar.
Feito isso, abra a janela Solution Explorer e clique com o botão direito do mouse sobre o nome do projeto, vá agora ao menu Add>New Item. Na janela que será apresentada, escolha a opção Class Diagram. Dê ao arquivo o nome de dgAcessoDados.cd. Esse arquivo especifica um diagrama de classes, que pode ser construído visualmente. Ou seja, utilizaremos o Visual Studio como ferramenta CASE, elaborando o projeto do framework inicialmente através de um diagrama. Na seqüência o Visual Studio criará automaticamente a classe, seus métodos e propriedades e adicionará a mesma ao nosso projeto.
Assim que o arquivo de diagrama for adicionado ele será automaticamente aberto. No centro da tela, aparecerá a opção de visualizar a janela ToolBox. Clicando sobre essa opção, vemos que vários componentes são dispostos. Estes componentes podem ser utilizados para construir dos mais simples aos mais complexos diagramas de classes, dentre estes temos:
- Class: Corresponde a uma classe. Nesta poderemos, visualmente, adicionar métodos, campos e propriedades.
- Enum: Define um tipo enumerado para ser utilizado no restante do projeto.
- Interface: De modo visual pode-se criar um molde para as classes que herdarem deste componente.
- Abstract Class: Com este componente, que na prática não pode ser instanciado, pode-se definir métodos, campos e propriedades que sempre serão herdados em classes filhas.
- Module: Cria um arquivo modular similar ao disponível no antigo Visual Basic 6. Usualmente utilizado para declarar classes e métodos públicos.
- Inheritance: Com este componente em forma de seta selecionado clique sobre uma classe a ser definida com pai, e sequentemente, na classe a ser definida como filha. Feito isso, um relacionamento de herança entre elas será criado automaticamente.
Continuando nosso projeto, arraste para a tela, um componente Class que se encontra na aba Class Designer (Figura 2). Quando fizer isso, uma janela aparecerá para que você indique algumas informações sobre a classe. Configure esta janela como na Figura 3 e clique em OK.
Executado esse procedimento, um diagrama representando uma classe será automaticamente adicionado na tela. É neste diagrama que vamos adicionar os métodos que constituirão nosso framework. Abra a janela Solution Explorer e repare que o arquivo de classe já foi criado, verificando o seu conteúdo podemos perceber que toda a estrutura de código também já foi adicionada pelo Visual Studio, no entanto, por enquanto não precisamos nos preocupar com o código, ou com quais bibliotecas iremos utilizar, estamos na fase de projeto.
Métodos de Conexão
Nossa camada de acesso vai interagir com o SQL Server Compact Edition de diversas formas. Precisaremos selecionar, apagar, inserir e alterar informações. Assim, com base nos objetos do ADO.NET 2.0 vamos definir os métodos a serem disponibilizados pela classe. Criaremos então o arquivo de classe passo-a-passo, iniciando com os métodos a seguir:
- AbreConexao(): Método que conecta ao banco de dados móvel.
- FechaConexao(): Método que desconecta a aplicação do banco de dados.
- CriaBD(nomeBD As String): Cria um banco de dados num path desejado.
Para adicionar um método no visual da classe, selecione o diagrama, clique com o botão direito sobre ele e vá ao menu Add>Method(). Quando o método for adicionado, defina o nome dele como AbreConexao e pressione ENTER. Repita esse passo, para os métodos FechaConexao e CriaBD. Vá ao código da classe e repare que os métodos já foram criados automaticamente.
Para que seja possível utilizar o banco de dados SQL Server Compact Edition, precisa-se adicionar uma referência a sua biblioteca. Para isso, clique com o botão direito sobre o nome do seu projeto na Solution Explorer, e vá ao menu Add Reference. Na aba .NET, encontre e selecione o namespace System.Data.SqlServerCe (Figura 4). Feito isso, clique em OK.
No código gerado não existe um namespace definido para esta classe, nem a importação das bibliotecas necessárias ao projeto, visto isso, modifique o código da biblioteca para que ele fique como o da Listagem 1.
Listagem 1 - Namespaces utilizados
Com a estrutura do framework definida, vamos agora implementar os métodos de conexão. Como já exibido na Listagem 1, crie uma variável que armazenará o objeto de conexão com o banco. Essa variável é do tipo SqlCeConnection e é responsável por conectar, operar e desconectar com a base de dados.
Código dos métodos de conexão
O método AbreConexao precisa sempre verificar o estado da conexão antes de abri-la, afinal, pode ser que mais de um aplicativo esteja acessando aquela base de dados. Para isso, ele se utiliza do método ConnectionState. Se a resposta for falsa, através de uma string de conexão (que em SQL Server CE é representada apenas pelo caminho do arquivo de extensão *.sdf) a conexão é realizada.
O método FechaConexao, faz a mesma verificação de estado do método de abertura. Se a resposta for verdadeira, ele finaliza a conexão.
Quando o banco de dados não existe no Pocket, pode-se utilizar o objeto Engine para a criação de um arquivo pronto de extensão *.sdf. O método a ser chamado é o CreateDatabase().
Preencha o conteúdo dos três métodos apresentados como nas Listagens 2, 3 e 4.
Listagem 2 - Método AbreConexao(banco as String)
Public Sub AbreConexao(ByVal banco as String)
Try
If (conexao.State = ConnectionState.Closed) Then
Dim strConexao As String = "data source=\Temp\”+ banco +”.sdf"
conexao = New SqlCeConnection(strConexao)
conexao.Open()
End If
Catch ex As Exception
Throw New Exception("Ocorreu um problema na conexão com o base de dados,
devido ao seguinte erro: " + ex.Message)
End Try
End Sub
Listagem 3 - Método FechaConexao()
Public Sub FechaConexao()
Try
If (conexao.State = ConnectionState.Open) Then
conexao.Close()
End If
Catch ex As Exception
Throw New Exception("Ocorreu um problema na conexão com o base de dados,
devido ao seguinte erro: " + ex.Message)
End Try
End Sub
Listagem 4 - Método CriaBD(nomeBD As String)
Sub CriaBD(ByVal nomeBD As String)
Dim sqlengine As New SqlCeEngine("data source=\Temp\" + nomeBD + ".sdf")
sqlengine.CreateDatabase()
End Sub
Métodos de Seleção de Dados
Agora vamos implementar os métodos que acessam a base de dados criada e retornam valores para serem trabalhados dentro do nosso aplicativo. Para isso, criaremos três métodos. Cada um deles através de uma string SQL terá como função preencher objetos DataSet, DataTable e DataReader. Acompanhe os métodos a serem criados nas Listagens 5, 6 e 7.
Listagem 5 - Método PreencheDataSet(dts as DataSet, sql as String)
Public Sub PreencheDataSet(ByVal dts As DataSet, ByVal sql As String)
Try
Dim da As New SqlCeDataAdapter(sql, conexao)
da.Fill(dts)
Catch ex As Exception
Throw New Exception("Ocorreu um problema na conexão com o base de dados,
devido ao seguinte erro: " + ex.Message)
End Try
End Sub
Listagem 6 - Método PreencheDataTable(dt as DataTable, sql as String)
Public Sub PreencheDataTable
(ByVal dt As DataTable, ByVal sql As String)
Try
Dim da As New SqlCeDataAdapter(sql, conexao)
da.Fill(dt)
Catch ex As Exception
Throw New Exception("Ocorreu um problema na conexão com o base de dados,
devido ao seguinte erro: " + ex.Message)
End Try
End Sub
Listagem 7 - Método PreencheDataReader(sql as String)
Public Function PreencheDataReader(ByVal sql As String) As SqlCeDataReader
Dim cmd As New SqlCeCommand(sql, conexao)
Dim dr As SqlCeDataReader = cmd.ExecuteReader()
Return dr
End Function
Cada um dos métodos criados espera por parâmetro uma string SQL e um objeto a ser preenchido. É importante ressaltar que no caso do método que visa o preenchimento de um DataReader não temos uma forma genérica de preenchimento. O objeto a ser definido no preenchimento é um SqlCeDataReader, se estivéssemos utilizando outro banco de dados seria necessário trocar a refêrencia a um objeto que desenhado para este banco determinado.
Métodos de Alteração, Exclusão e Inserção de Dados
É imprescindível na maioria das aplicações que possamos manipular os dados existentes em uma base de dados. Assim, criaremos agora o método que executa strings SQL na base de dados e não retorna nenhum tipo de valor, ou seja, visa alterar, incluir ou deletar dados. Acompanhe o métodos citado na Listagem 8.
Listagem 8 - Método ExecutaComandoSQL(sql as String)
Public Sub ExecutaComandoSQL(ByVal sql As String)
Try
Dim cmd As New SqlCeCommand(sql, conexao)
cmd.ExecuteNonQuery()
Catch ex As Exception
Throw New Exception("Ocorreu um problema na conexão com o base de dados,
devido ao seguinte erro: " + ex.Message)
End Try
End Sub
Nesse métodos criamos um objeto do tipo SqlCeCommand para executar um comando em nossa base de dados, essa execução é definida através do ExecuteNonQuery().
Métodos para Transações
Em alguns de nossos aplicativos precisamos às vezes operar processos que sejam, ou executados com completo sucesso, ou que não sejam executados. Por exemplo, se na sua aplicação fosse necessário inserir um milhão e meio de registros em uma tabela e essa operação levasse 1 hora para ocorrer. Certo, imagine agora que no meio da operação, uma pane no sistema ocorra, um dano no hardware, por exemplo. Apenas metade dos registros seria inserida, em outras palavras a ação ficaria incompleta. Em sistemas bancários, uma ocorrência como essa pode definir se uma quantia de dinheiro foi ou não depositada em uma conta, o que caracteriza um sério risco. Para tratar eventos como esses, a maioria dos SGBD´s vem equipado com sistemas de transação, que tem por função gerenciar processos enquanto ocorrem, e se alguma coisa de errado acontecer enquanto o processo roda, ele inteiro é desfeito. Veja nos métodos apresentados nas Listagens 9 e 10, como aplicar esse conceito ao SQL Server CE.
Listagem 9 - Método IniciaTransacao()
Public Sub IniciaTransacao()
Try
If (conexao.State = ConnectionState.Open) Then
transacao = conexao.BeginTransaction
End If
Catch ex As Exception
Throw New Exception("Ocorreu um problema na conexão com a base da dados,
devido ao seguinte erro: " + ex.Message)
End Try
End Sub
Listagem 10 - Método FinalizaTransacao()
Public Sub FinalizaTransacao(ByRef flag As Boolean)
If flag = False Then
transacao.Commit()
Else
transacao.Rollback()
End If
End Sub
Exemplo de utilização do framework de acesso a dados
Para finalizar este artigo vamos agora ver um pequeno exemplo onde utilizaremos o framework criado. Inicialmente, modifique o arquivo chamado Form1.vb para frmProjeto.vb. Abra esse formulário e configure-o da forma como é apresentado na Figura 5.
Após criar o menu, com as opções de criar um banco, conectar e desconectar, vamos codifica-los utilizando nosso framework para acesso a dados, num exemplo simples e hipotético. Clique duas vezes sobre a opção destinada a codificação e correspondentemente insira nos eventos os códigos da Listagem 11. Repare, como apresentado na Figura 6, como o encapsulamento das funções criadas é apresentado de forma intuitiva. Estamos uma camada acima das ações que manipulam a base de dados.
Listagem 11 – Code-Behind do frmProjeto.vb
Dim con As New Conexoes.conexaoSQLServerCE
Private Sub cmdCriaBanco_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles cmdCriaBanco.Click
con.CriaBD("bd_teste")
MsgBox("Banco criado com sucesso!")
End Sub
Private Sub cmdConecta_Click(ByVal sender As System.Object, ByVal e
As System.EventArgs) Handles cmdConecta.Click
con.AbreConexao("bd_teste")
MsgBox("Conexão estabelecida!")
End Sub
Private Sub cmdDesconecta_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles cmdDesconecta.Click
con.FechaConexao()
End Sub
Inserido os códigos, aperte F5. Quando o projeto for executado, uma janela perguntando qual emulador deseja utilizar será apresentada. Escolha um ao seu gosto. Clique nas opções e repare como o projeto executa. É interessante dizer que um framework como o que desenvolvemos nesta aplicação pode ser utilizado em qualquer tipo de projeto .NET. Ao executar essa aplicação um arquivo DLL foi compilado e se encontra na pasta BIN de nosso projeto. Se precisar utilizá-lo e não quiser copiar a classe novamente, basta fazer uma referência a este arquivo de extensão DLL. Muito simples e rápido! Para projetos desktop, ou WEB pode-se também utilizar esta mesma estrutura de framework, modificando apenas a biblioteca que se deseja fazer acesso, no nosso caso utilizamos a System.Data.SqlServerCe.
Bem pessoal, é isso, espero que façam bastante proveito desse framework, especialmente útil para trabalhar em camadas.