ADO - Trabalhando com Recordsets sem uma base de dados
Qual seria sua reação se alguém dissesse que pode trabalhar com Recordsets ADO sem utilizar qualquer fonte de dados externa ? Espanto ? Descrença ? Curiosidade ? ...
Qualquer que seja a sua reação vou logo dizer que isto é perfeitamente possível e viável e com algumas vantagens . Quer saber quais são elas ?
Você não precisa criar um banco de dados ( Uau... )
Como o seu sistema não depende de uma base de dados externas ele fica mais portátil
Você não tem que se preocupar em como se conectar a uma base de dados ( ela não existe .. :-)
A quantidade de código fica reduzida e a manutenção fica mais fácil
Sua aplicação fica com um tamanho menor e necessita de menos recursos para ser executado.
Você usa todo o seu conhecimento sobre o modelo de objeto ADO
Bem , se você ainda esta incrédulo , e , é daqueles que precisa ver para crer , vamos mostrar uma aplicação completa com um recordset ADO sem usar um banco de dados. ( se quiser pode dar uma olhada no artigo - Retornando dados com GetRows - onde já arranhamos o assunto...)
Vamos criar um pequeno programa , uma agenda pessoal , para armazenar os endereços dos amigos , parentes , etc... Estaremos trabalhando com as opções de incluir , alterar e excluir os registros do nosso arquivo de dados, tudo isto sem usar um banco de dados...
Criando a aplicação - Agenda
Inicie um novo projeto no VB padrão Standard EXE
Escolha no menu principal a opção Projetct | References e selecione - Microsoft ActiveX Data Objects 2.x ( versão superior a 2.0 )
Agora insira os controles no formulário padrão como exibidos na figura abaixo:
Estamos usando : um controle ListView(ListAgenda) , sete textbox(0...7) , sete labels (0...7) , um frame e três botões de comando: cmdincluir, cmdsalvar, cmdexcluir
Pronto o 'esqueleto' já esta montado , vamos agora para o 'recheio' - o código...
Você deve estar se perguntando - Como vamos usar um Recordset sem um banco de dados ?
Se você ainda não sabe , a ADO permite utilizar um recordset desconectado . É este conceito que vamos usar. Podemos desconectar e mais tarde fazer a conexão com uma base de dados , mas este não vai ser nosso caso. Simplesmente vamos usar o recordset desconectado. Para definir um recordset desconectado podemos dizer que: "Um recordset desconectado é um recordset do lado do cliente que não tem uma conexão ativa a uma fonte de dados ou banco de dados."
Só para você ter uma idéia da utilidade desta técnica , imagine um servidor de banco de dados que pode lidar com apenas um certo número limitado de conexões ativas ao mesmo tempo. Assim quando um aplicativo precisa esperar a entrada do usuário ou qualquer outra ação do usuário , porque manter a conexão aberta por todo este tempo ?
Você pode , no caso acima, recuperar os dados de uma fonte de dados , armazenar os dados em um recordset e desconectar o recordset da fonte de dados para libera recursos da conexão. O aplicativo altera os dados ou incluir novos dados ao recordset e depois se reconecta e a fonte de dados e escreve as mudanças ocorridas. Entendeu ???
As duas principais técnicas para criar um recordset desconectado são :
Prepare e abra um recordset do lado do cliente e preencha-o com os dados do banco de dados; A seguir desconecte o Recordset ( veja abaixo ) .
Prepare um recordset do lado do cliente e apos definir as propriedades dos campos use o método Open para que o recordset seja preenchido com os registros.
A primeira coisa a fazer para gerar um recordset (rsagenda) desconectado é :
criar uma variável objeto - Set rsagenda = ADODB.Connection
a seguir definir a conexão ativa através da propriedade ActiveConnection para Nothing - Set ActiveConnection = Nothing
Definir o tipo do cursor como estando do lado do Cliente - CursorLocation = adUseClient
Pronto , já temos nosso recordset desconectado e pronto para ser usado. Precisamos no entanto fazer os ajustes finais , os quais sejam :
Definir o tipo de bloqueio - LockType = adLockBatchOptimistic - indicando que as atualizações no recordset ocorrerão no modo otimista e em lote. ( durante a edição outros usuários não poderão alterar o conteúdo do registro)
E a estrutura do Recordset ? de onde virá ?
Bem . como não estamos usando um banco de dados vamos ter que criar a estrutura do recordset. Para fazer isto usamos o método Append da coleção Fields e incluímos a definição de cada campo ao recordset. Para fazer isto vamos precisar conhecer o nome , tamanho e o tipo de dados de cada campo.
A sintaxe para para o método Append é :
objetoRecordset.Fields .Append NomeCampo , TipoCampo , TamanhoCampo , Atributos
O nome e o tamanho dos campos são definidos com base nas informações que desejamos armazenar. Assim, para o nosso caso , vamos armazenar : o nome , endereço ,cidade , cep , uf , telefone e email. Podemos definir o nome e o tamanho conforme a tabela abaixo :
AgEndereco 50
AgCidade 40
AgCep 15
Aguf 2
Agtelefone 15
Agemail 250
E o tipo de dados , como vamos definir ? Abaixo temos os principais tipos de dados suportados na ADO :
adBinary Um valor binário (DBTYPE_BYTES).
adBoolean Um valor Boleano (DBTYPE_BOOL).
adBSTR Um caractere string terminado em null-(Unicode) (DBTYPE_BSTR).
adChar Um valor String fixo. (DBTYPE_STR).
adCurrency Um valor monetário (DBTYPE_CY).
adDate Um valor Data (DBTYPE_DATE).
adDBDate Um valor Data (yyyymmdd) (DBTYPE_DBDATE).
adDBTime Um valor para horas (hhmmss) (DBTYPE_DBTIME).
adDecimal Um valor numérico exato com precisao defnida.(DBTYPE_DECIMAL).
adDouble Valores de precisao dupla (DBTYPE_R8).
adEmpty Um valor não definido (DBTYPE_EMPTY).
adInteger Um inteiro de 4 bytes (DBTYPE_I4).
adNumeric Um valor numerico (DBTYPE_NUMERIC).
adSingle Precisão simples (DBTYPE_R4).
adVarChar Um valor String (Parameter object only).
adVariant Um valor Variant (DBTYPE_VARIANT).
Como no nosso exemplo todos os campos são do tipo Texto podemos usar então o tipo de dado adVarChar ou adBSTR . Vamos usar advarChar.
O parâmetro Atributos ( Attributes ) é opcional e define atributos para os novos campos : EX: Conter valores NULL - adFldMaybeNull. O valor padrão é adFldDefault .
Nosso recordset será criando conforme o código a seguir:
.Append "Nome", adVarChar, 50
.Append "Endereco", adVarChar, 50
.Append "Cidade", adVarChar, 40
.Append "Cep", adVarChar, 15
.Append "UF", adVarChar, 2
.Append "telefone", adVarChar, 15
.Append "email", adVarChar, 250
]E como fazemos para salvar o Recordset ?
Simples, use o método Save do objeto Recordset.
A sintaxe para o método Save é:
Destination - Um variant que representa o caminho completo do arquivo onde o Recordset será salvo , pode ser também uma referência um objeto Stream
PersistFormat - Um valor PersistFormatEnum que define o formato no qual o Recordset será salvo , os formatos possíveis são:
XML - adPersistXML HTML - adPersistHTML e o padrão adPersistADTG
Ex: rsagenda.Save "c:\teste\agenda.dat" , adPersistADTG
O método Save somente pode ser invocado em um Recordset aberto . Antes de usá-lo você deve usar o método Open para restaurar o recordset a partir do destino.
Se a propriedade Filter estiver ativa no Recordset , então , somente as linhas acessíveis no filtro serão salvas.
Ao salvar as alterações no recordset ele permanece aberto e você pode salvar as mudanças mais recentes.
Para alcançar um bom desempenho usando Save utilize a propriedade CursorLocation como adUseClient.
Vamos agora ao código das funções utilizadas no aplicativo agenda:
Na seção General Declarations do formulários insira o código abaixo , onde definimos as variáveis visíveis em todo o formulário.
Public rsagenda as ADODB.Recordset
A seguir teremos o código que inicializa o nosso objeto recordset - rsagenda. O código estará no evento Load do Formulário. Vejamos:
Set rsagenda = New ADODB.Recordset
Call Abre_Recordset_Desconectado
Call Preenche_Lista
If rsagenda.RecordCount > 1 Then
rsagenda.Filter = "Nome='" & ListAgenda.SelectedItem.Text & "'"
Call Preenche_Controles
A procedura Abre_Recordset_Desconectado , verifica se o arquivo agenda.dat ( voce pode usar qualquer nome).Se o arquivo não existir ele será criado através da rotina Cria_Recordset_Desconectado:
Private Sub Abre_Recordset_Desconectado()
strArquivo = "c:\teste\agenda.dat"
If Dir(strArquivo) = "" Then
Cria_Recordset_Desconectado
rsagenda.Open strArquivo
A rotina Cria_Recordset_Desconectado abaixo irá criar o recordset rsagenda com a estrutura já definida:
Private Sub Cria_Recordset_Desconectado()
With rsagenda
.Save strArquivo, adPersistADTG
A seguir a rotina Preenche_Lista irá preencher o controle ListView com os dados do recordset exibindo somente o nome constante no recordset. Abaixo o código:
With ListAgenda
Do Until rsagenda.EOF
Set newitem = .ListItems.Add(, , rsagenda("Nome"))
rsagenda.MoveNext
Set ListAgenda.SelectedItem = newitem
A seguir usamos a propriedade Filter do recordset para filtrar o recordset , Assim :
Perceba que o filtramos pelo campo Nome igual ao item atualmente selecionado na Lista.
Depois preenchemos os controles através da procedura Preenche_Controles abaixo:
Private Sub Preenche_Controles()
If rsagenda.RecordCount > 0 Then
For icontador = 0 To rsagenda.Fields.Count - 1
Set Text1(icontador).DataSource = rsagenda
Text1(icontador).Text = rsagenda.Fields(icontador)
Para incluir dados no recordset basta clicar no botão - Incluir (cmdIncluir). O código é o seguinte:
Private Sub cmdincluir_Click(Index As Integer)
ListAgenda.Sorted = False
Set ListAgenda.SelectedItem = Nothing
Text1(icontador).Text = ""
A exclusão de um registro é obtida ao clicarmos no botão - Excluir (cmdexcluir) - cujo código é:
Private Sub cmdexcluir_Click(Index As Integer)
rsagenda.Delete adAffectCurrent
rsagenda.Filter = "Nome='" & .SelectedItem.Text & "'"
A rotina mais importante é que salva o recordset em um arquivo definido . Usamos o arquivo agenda.dat . O botão cmsalvar ao ser clicado dispara o seguinte código:
rsagenda.AddNew
rsagenda.Fields(icontador) = Text1(icontador).Text
Call Salvar_Recordset_Desconectado
Abaixo a procedure ListAgenda_ItemClick que atualiza os controles quando clicamos em um item da lista.
Private Sub ListAgenda_ItemClick(ByVal Item As MSComctlLib.ListItem)
Finalmente o código do evento Query_Unload que salva o recordset quando o usuário sai do aplicativo :
rsagenda.Save strArquivo, adPersistADTG
Abaixo a tela do aplicativo em funcionamento:
Viu como tratamos um recordset sem precisar de uma conexão com um banco de dados. A vantagem é que podemos usar quase todos os métodos e propriedades do objeto recordset ( addnew, delete , Filter , Sort , etc.. )
Eu não usei um tratamento de erros no exemplo , nem me preocupei com alguns possíveis erros , meu objetivo foi mostrar como trabalhar um recordset desconectado.