Desde
o princípio o FoxPro é famoso por seu poder de acesso a dados.
Inicialmente, impressionava pela velocidade e facilidade em fazê-lo. Hoje
em dia, há muito mais que isso. A flexibilidade sem dúvida impressiona
muito mais. Teoricamente diz-se que através do Visual FoxPro pode-se
acessar qualquer tipo de fonte de dados, desde que essa tenha conectividade
através de ODBC, OLEDB ou ADO. No entanto, praticamente qualquer linguagem
é capaz de fazê-lo também. Mas na prática temos visto
que o Visual FoxPro é capaz de processar dados remotos (de outras fontes
que não seja o DBC) com uma performance muito superior a outras linguagens.
No
Visual FoxPro 8.0 foi introduzido um novo conceito de acesso a dados. Trata-se
de uma classe orientada a objetos chamada CursorAdapter.
Através
da classe CursorAdapter, que traduzido para o português quer dizer adaptador
de cursores, podemos trabalhar com dados das mais diversas fontes sem nos preocupar
muito com os detalhes da tecnologia do banco de dados remoto, ou mesmo em aprender
os recursos do Driver ODBC ou OLEDB que provêem acesso à fonte
de dados remota.
A
classe encapsula o conhecimento sobre como transformar os dados remotos em dados
locais do Visual FoxPro. Isso mesmo! O dado remoto é transformado em
um cursor, o que facilita o trabalho do desenvolvedor. Quando da necessidade
de enviar os dados do cursor para a fonte remota, a classe CursorAdapter sabe
muito bem o que fazer. Prepara os dados, e envia para a fonte, assegurando que
sejam gravados corretamente.
Antes
da versão 8.0 do VFP precisávamos escrever nossas próprias
classes de acesso a dados para trabalhar com fontes de dados externas. Geralmente
utilizava-se objetos RecordSet da biblioteca ADO para acesso orientado a objetos.
Para acesso através de programação não OOP, utilizava-se
outros recursos como Remote Views e SQL Pass-Through.
Um
aplicativo construído com Remote Views usando um banco de dados MS SQL
Server, se necessário alterar para uso com Oracle teria no mínimo
que refazer as Views. Com o uso de CA’s (CursorAdapter’s) as alterações
seriam bem menos traumáticas. Como as CA’s são classes OOP,
é totalmente possível criarmos classes mais especializadas capazes
de agregar novos recursos e até mesmo novas funcionalidades, fazendo
com que o acesso a dados em VFP continue sendo insuperável por qualquer
outra ferramenta.
Através
da classe CursorAdapter podemos acessar dados das seguintes fontes de dados:
. Nativa (DBF/DBC)
. ODBC
. ADO
. XML
. ODBC
. ADO
. XML
Vejamos o que significa cada tipo de fonte de
dados:
NATIVE
-Indica que o objeto CursorAdapter trabalhará com dados nativos do Visual
FoxPro (banco DBC/tabelas DBF).
ODBC
- Indica que a classe CursorAdapter trabalhará com fontes de dados que
serão acessadas através de drivers ODBC. É possível
acessar dados remotos numa rede ou fora dela.
ADO
- Indica que a classe CursorAdapter usará a biblioteca ADO para acessar
a fonte de dados. A biblioteca ADO trabalha com biblioteca de drivers OLEDB,
que são mais atualizados que os drivers ODBC.
XML
- Indica que a classe CursorAdapter trabalhará com documentos XML como
fonte de dados.
Quando
usando fontes de dados ODBC e ADO, necessita-se de uma conexão estabelecida
previamente com o banco de dados.
Para
ODBC, podemos estabelecer a conexão através das funções
SQLCONNECT() e SQLSTRINGCONNECT(). Veja posteriormente ainda neste capítulo
as definições para estas funções.
Principais
PEM's da classe CursorAdapter
Antes
de prosseguirmos, vamos conhecer as principais propriedades, eventos e métodos
da classe CursorAdapter. A partir do conhecimento das PEM's desta classe, poderemos
melhor aproveita-la.
Eventos
do Objeto CursorAdapter
Evento Descrição AfterCursorAttachOcorre imediatamente depois que o método CursorAttach é executado.AfterCursorCloseOcorre depois que o objeto CursorAdapter é fechadoAfterCursorDetachOcorre imediatamente depois que o método CursorDetach é executado.AfterCursorFillOcorre depois que o método CursorFill é executado.AfterCursorRefreshOcorre imediatamente após o método CursorRefresh ser executado.AfterCursorUpdateOcorre depois que qualquer dado do cursor seja atualizado através da função TABLEUPDATE().AfterDeleteOcorre sempre depois que um comando DELETE seja executado.AfterInsertOcorre sempre depois que um comando INSERT é executado.AfterUpdateOcorre imediatamente depois que uma operação de atualização é executada para um registro.BeforeCursorAttachOcorre imediatamente antes que o objeto CursorAdapter tente unir (attach) um cursor. Você pode usar este evento para executar todas as operações necessárias antes de unir (attach) o cursor ou tabela, determinar um apelido (alias) para a união (attach), e assim por diante.BeforeCursorCloseOcorre imediatamente antes que um cursor se feche. Você pode usar este evento para executar todas as operações necessárias antes de fechar um cursor ou tabela, e assim por diante.BeforeCursorDetachOcorre antes do método CursorDetach ser executado.Você pode executar este evento para executar todas as operações necessárias antes de desanexar o cursor ou a tabela.BeforeCursorFillOcorre imediatamente antes do método CursorFill ser executado.BeforeCursorRefreshOcorre antes do método CursorRefresh ser executado.BeforeCursorUpdateOcorre imediatamente antes da função TABLEUPDATE() ser executada.BeforeDeleteOcorre imediatamente antes que um comando de deleção de registro seja executado.BeforeInsertOcorre imediatamente antes de um comando de inserção de registro ser executado.BeforeUpdateOcorre imediatamente antes de um comando de atualização para um registro.
Principais
Propriedades do Objeto CursorAdapter
Propriedade Descrição AliasEspecifica um apelido para a tabela a ser gerada pelo objeto CursorAdapter.AllowDeleteEspecifica se os dados apagados num cursor são submetidos para a origem de dados.AllowInsertEspecifica se os dados inseridos no cursor são enviados para a origem de dados.AllowUpdateEspecifica se os dados modificados num cursor associado a um objeto CursorAdapter são enviados para a origem de dados.ConversionFuncEspecifica funções para conversão de dados.
CursorSchemaEspecifica o formato de dados para o cursor local gerado. DataSourceEspecifica a conexão com a origem de dados. DataSourceTypeEspecifica o tipo de origem de dados.
KeyFieldListEspecifica a lista de campos chave para o CursorAdapter.SelectCmdEspecifica o comando para recuperar (consultar) dados da origem de dados.SendUpdatesEspecifica se os dados resultantes de uma consulta em um objeto CursorAdapter são enviados para a origem de dados.TablesEspecifica quais tabelas devem ser atualizadas para operações de inserção, alteração ou remoção quando um objeto CursorAdapter aceita atualizações. Quando mais de uma tabela, separa-las por vírgula.UpdatableFieldListLista de campos atualizáveis.
UpdateNameListLista contendo os nomes dos campos atualizáveis em pares identificando o campo na tabela loca e o respectivo campo na tabela remota.
Principais
Métodos do Objeto CursorAdapter
Método Descrição AutoOpenExecuta o método CursorFill sem passar nenhum parâmetro padrão. Quando o objeto CursorAdapter está dentro do ambiente de dados de um formulário, o ambiente de dados chama o método AutoOpen automaticamente dentro do método OpenTables do ambiente de dados.CursorAttachAnexa um cursor existente à uma instância já existe de um objeto CursorAdapter.CursorDetachLibera um cursor anexado à uma instância do objeto CursorAdapter sendo executado.CursorFillExecuta o comando da propriedade SelectCmd de acordo com o DataSource selecionado, cria um cursor com os dados recuperados, executa a conversão de dados necessária de acordo com as propriedades DataSourceType e CursorSchema.CursorRefreshAtualiza um cursor com os dados atuais da origem de dados.
Acessando
dados nativos (DBC/DBF) com CursorAdapter
Uma boa forma
de iniciar os estudos da classe CursorAdapter é utilizando os dados nativos
do Visual FoxPro. Sim, aqueles que geralmente usamos comandos xBase como OPEN
DATABASE, USE, etc., para abrir, o banco de dados.
Vejamos o exemplo
da listagem 1 a seguir:
Listagem 1:
LOCAL
loCAClientes AS CursorAdapter
OPEN DATABASE _Samples + "Northwind\Northwind.dbc"
OPEN DATABASE _Samples + "Northwind\Northwind.dbc"
*!*
Instancia a classe CursorAdap
loCAClientes = CREATEOBJECT("CursorAdapter")
loCAClientes.DataSourceType = "NATIVE" && Banco nativo
loCAClientes.DataSource = "" && Origem de dados
loCAClientes.Alias = "Clientes"&& Define o Alias
loCAClientes.SelectCmd = "SELECT * FROM Customers"
loCAClientes = CREATEOBJECT("CursorAdapter")
loCAClientes.DataSourceType = "NATIVE" && Banco nativo
loCAClientes.DataSource = "" && Origem de dados
loCAClientes.Alias = "Clientes"&& Define o Alias
loCAClientes.SelectCmd = "SELECT * FROM Customers"
IF
loCAClientes.CursorFill()
BROWSE FONT 'Courier New',12 && Exibe os dados da tabela
ELSE
MESSAGEBOX("Cursor não criado!",0+16,"Erro")
ENDIF
CLOSE
DATABASES ALL
Ao
executar o exemplo acima teremos o seguinte resultado:

Figura 1 - Cursor
criado pelo objeto loCAClientes
Examinando o
código da listagem 1 podemos verificar as seguintes ações:
- OPEN DATABASE _Samples + "Northwind\Northwind.dbc" - usamos um commando nativo do VFP para abrir o banco de dados Northwind.dbc.
- loCAClientes = CREATEOBJECT("CursorAdapter") - instanciamos a classe CursorAdapter nativa do Visual FoxPro.
- Definimos as propriedades mínimas para o funcionamento de nossa consulta:
loCAClientes.DataSourceType=
"NATIVE" && Banco nativo
loCAClientes.DataSource = "" && Origem de dados
loCAClientes.Alias = "Clientes" && Define o Alias
loCAClientes.SelectCmd = "SELECT * FROM Customers"
loCAClientes.DataSource = "" && Origem de dados
loCAClientes.Alias = "Clientes" && Define o Alias
loCAClientes.SelectCmd = "SELECT * FROM Customers"
-
Finalmente executamos o método responsável por enviar a solicitação da consulta ao banco de dados e criar o cursor resultante:
loCAClientes.CursorFill()
Como é
notório, não é nada complicado o uso básico da classe
CursorAdapter. É importante lembrar que a estamos utilizando a partir
de um PRG. Para uso em um formulário há alguns cuidados a tomar
que serão tratados posteriormente, em outro artigo.
Embora
o cursor gerado com o código da listagem 1 seja de leitura e escrita,
os dados alterados não serão enviados para a origem de dados,
ou seja, nenhuma atualização será realizada nos dados originais.
A seguir, veremos como tornar a origem de dados atualizável.
Atualizando
os dados na Origem de Dados
No
exemplo anterior fizemos uma consulta a uma origem de dados nativa. Embora o
cursor resultante seja de leitura e escrita, qualquer alteração
que fizermos em seus dados, não será enviada para a origem de
dados. Para que essas modificações reflitam no banco de dados
de origem é necessário preencher corretamente as propriedades
SendUpdates, Tables, KeyFieldList, UpdatableFieldList, UpdateNameList.
Na
próxima listagem de código, denominada listagem 2, partimos do
código da listagem 1, acrescentando as linhas de código necessárias
para enviar os dados alterados para a origem de dados.
Listagem 2:
LOCAL
loCAClientes AS CursorAdapter
OPEN DATABASE _Samples + "Northwind\Northwind.dbc"
*!* Instancia a classe CursorAdapter
loCAClientes = CREATEOBJECT("CursorAdapter")
loCAClientes.DataSourceType = "NATIVE" && Banco nativo
loCAClientes.DataSource = "" && Origem de dados
loCAClientes.Alias = "Clientes"&& Define o Alias
loCAClientes.SelectCmd = "SELECT * FROM Customers"
OPEN DATABASE _Samples + "Northwind\Northwind.dbc"
*!* Instancia a classe CursorAdapter
loCAClientes = CREATEOBJECT("CursorAdapter")
loCAClientes.DataSourceType = "NATIVE" && Banco nativo
loCAClientes.DataSource = "" && Origem de dados
loCAClientes.Alias = "Clientes"&& Define o Alias
loCAClientes.SelectCmd = "SELECT * FROM Customers"
*!*
As linhas a seguir tornam a origem de dados atualizável
loCAClientes.SendUpdates = .T.
loCAClientes.Tables = "Customers"
loCAClientes.KeyFieldList = "CustomerID"
loCAClientes.UpdatableFieldList="CompanyName, ContactName, Country"
loCAClientes.UpdateNameList = "CustomerID Customers.CustomerID, "+;
"CompanyName Customers.CompanyName, "+;
"ContactName Customers.ContactName, "+;
"Country Customers.Country"
loCAClientes.SendUpdates = .T.
loCAClientes.Tables = "Customers"
loCAClientes.KeyFieldList = "CustomerID"
loCAClientes.UpdatableFieldList="CompanyName, ContactName, Country"
loCAClientes.UpdateNameList = "CustomerID Customers.CustomerID, "+;
"CompanyName Customers.CompanyName, "+;
"ContactName Customers.ContactName, "+;
"Country Customers.Country"
*!*
As linhas a seguir tornam a origem de dados atualizável
IF loCAClientes.CursorFill()
IF loCAClientes.CursorFill()
BROWSE FONT 'Courier New',12 && Exibe os dados da tabela
ELSE
MESSAGEBOX("Cursor não criado!",0+16,"Erro")
ENDIF
CLOSE
DATABASES ALL
A
diferença do código da listagem 2 em relação do
código da listagem 1 são as linhas de código a seguir:
*!*
As linhas a seguir tornam a origem de dados atualizável
loCAClientes.SendUpdates
= .T.
loCAClientes.Tables = "Customers"
loCAClientes.KeyFieldList = "CustomerID"
loCAClientes.UpdatableFieldList="CompanyName, ContactName, Country"
loCAClientes.UpdateNameList = "CustomerID Customers.CustomerID, "+;
"CompanyName Customers.CompanyName, "+;
"ContactName Customers.ContactName, "+;
"Country Customers.Country"
loCAClientes.Tables = "Customers"
loCAClientes.KeyFieldList = "CustomerID"
loCAClientes.UpdatableFieldList="CompanyName, ContactName, Country"
loCAClientes.UpdateNameList = "CustomerID Customers.CustomerID, "+;
"CompanyName Customers.CompanyName, "+;
"ContactName Customers.ContactName, "+;
"Country Customers.Country"
Observe
que as propriedades SendUpdates, Tables, KeyFieldList, UpdatableFieldList, UpdateNameList
que foram citadas anteriormente como sendo pré-requisito para que os
dados sejam atualizados na origem de dados estão presentes nessas linhas
de código e consequentemente os dados podem ser atualizados na origem
de dados. Para confirmar o que estou afirmando aqui, o melhor a fazer é
executar o código e realizar qualquer alteração sobre os
dados das colunas CompanyName, ContactName e Country. Qualquer alteração
realizada em qualquer outra coluna não será enviada para a origem
de dados, uma vez que estas não estão listadas nas propriedades
UpdatableFieldList e UpdateNameList. Veja a figura 2 com dados alterados na
coluna CompanyName, onde acrescentei Brazil ao final. Para que a alteração
seja enviada para a origem de dados basta movimentar o ponteiro do registro
para o próximo registro.

Figura 2 - Dados
alterados no cursor são enviados para a origem de dados
Analisemos
agora o que cada linha de código adicionada neste PRG realiza efetivamente.
-
Na linha de código a seguir, dizemos ao objeto loCAClientes que qualquer alteração deve ser enviada para a origem de dados. No entanto, o sucesso do envio dessas alterações dependerá da definição das demais propriedades que discutiremos a nos próximos tópicos:
loCAClientes.SendUpdates
= .T.
-
Agora especificamos qual é a tabela que deve ser alterada na origem de dados:
loCAClientes.Tables
= "Customers"
-
Aqui indicamos qual é o campo chave da tabela:
loCAClientes.KeyFieldList
= "CustomerID"
-
A seguir passamos a lista de campos que queremos que sejam atualizáveis na origem de dados. Cada campo é separado por vírgula:
loCAClientes.UpdatableFieldList="CompanyName,
ContactName, Country"
-
A última propriedade é responsável por fazer um mapeamento dos campos do cursor gerado pelo objeto CursorAdapter com os campos da tabela na origem de dados, onde o campo do lado esquerdo do par representa o campo do cursor e a seqüência nometabela.nomecampo representa a tabela e o campo na origem da dados:
loCAClientes.UpdateNameList=
"CustomerID Customers.CustomerID, "+;
"CompanyName Customers.CompanyName, "+;
"ContactName Customers.ContactName, "+;
"Country Customers.Country"
"CompanyName Customers.CompanyName, "+;
"ContactName Customers.ContactName, "+;
"Country Customers.Country"
Até
aqui nada complicado. Diria que torna-se um pouco tedioso e meio repetitivo
a tarefa de informar os dados das propriedades UpdatableFieldList e UpdateNameList,
mas fora isso, o processo é bastante simples.
Fonte: http://imasters.com.br/artigo/3958/desenvolvimento/acesso-a-dados-com-a-classe-cursoradapter
Creditos: Nilton Paulino
Nenhum comentário:
Postar um comentário