Gravando dados

Foto de Anderson

gravando dados em clipperGravando no banco de dados do Clipper em modo multiusuário. Observe os comentário no exemplo abaixo.

 

// Abre arquivo CLIENTE (banco de dados) e o apelida como 'CLI'.
// Toda vez que tiver um 'CLI->' se refere a um campo do arquivo CLIENTE 
// ou função que rode como se desse um SELECT CLIENTE 
USE CLIENTE ALIAS CLI SHARED NEW
SET INDEX TO CODCLI
// Definicao de variaveis
// técnica: letra inicial da variavel igual ao tipo da variavel: c = caracter
cNOME := SPACE(30)
cEND  := SPACE(35)
CLS
@ 10,10 SAY "Nome:" GET cNOME
@ 11,10 SAY "Endereço:" GET cEND
READ
nCOD := NOVOCOD("CODCLI.DAT") // Falarei mais detalhadamente mais adiante

// a chamada ao DBAPPEND() ou ao APPEND BLANK já faz um bloqueio
// automatico no registro, sendo desnecessario a nossa função BLOQREG() (tópico 1)
// até porque, se não fosse, o clipper retornaria um erro.
CLI->(DBAPPEND()) // Função que insere um registro em branco no arquivo CLIENTE (apelidado CLI),
//                   veja uma observacao no final.
// Note como são referenciados as variaveis do arquivo: alias->campo do arquivo
CLI->NOME     := cNOME
CLI->ENDERECO := cEND
CLI->CODIGO   := nCOD
CLI->(DBUNLOCK()) // libera o registro p/ uso
CLI->(DBCOMMIT()) // assegura a integridade do DBF
// [...]
FUNCTION NOVOCOD(ARQUIVO)
IF !FILE(ARQUIVO)                  // se não existir o arquivo
   nHandle := FCREATE(ARQUIVO, 0)  // então, cria o arquivo
   IF FERROR() # 0
      ALERT("Erro"+ALLTRIM(STR( FERROR() ))+": Arquivo não pode ser criado!!!" )
      QUIT
   ELSE
      // deu certo! arquivo criado em branco.
      FWRITE(nHandle, "000000") // grava 000000 no arquivo. O código irá até 999999.
      FCLOSE(nHandle)           // fecha arquivo
   ENDIF
ENDIF
nHandle := FOPEN(ARQUIVO, 66) // abre arquivo
IF FERROR() != 0
   ALERT("Erro"+ALLTRIM(STR( FERROR() ))+": Arquivo não pode ser aberto!!" )
   QUIT
ENDIF
nCOD := VAL( FREADSTR(nHANDLE, 6) ) // lê o arquivo e armazena o conteúdo dele em nCOD
nCOD++  // acrescenta +1
FSEEK(nHANDLE, 0)
FWRITE(nHANDLE, STRZERO(nCOD,6)) // grava novo código no arquivo
FCLOSE(nHANDLE)                  // fecha o arquivo
RETURN (nCOD)

Assim deverá ser a rotina de gravação de um arquivo em modo compartilhado. Agora vamos a algumas observações.

nCOD := NOVOCOD("CODCLI.DAT"))

Os arquivos DBF em rede tem problema de integridade, que devem ser minimizados com medidas de segurança por parte do programador. Refiro-me a integridade dos arquivos de índice principalmente. Já pensou se você atribuisse o novo código desta forma:

CLI->(DBGOBOTTOM())
nCOD := CLI->CODIGO + 1

E o seu arquivo de indice estivesse corrompido??? Geraria um código repetidos e comprometeria a consistência do arquivo, que teria dois códigos iguais.

Mas e se você fizesse assim:

nCOD := CLI->(LASTREC()) +1

E quisesse excluir algum registro??? Também não daria certo!

O melhor então é criar um arquivo separado, de texto, que guarde o valor do código atual, para que a chamada da nossa função retorne o novo código, como foi feito na função NOVOCOD().

Observação: Caso você precise de vários DBF's com um campo de código p/ chave primária, uma outra solução é criar uma base de dados com apenas um registro e, vários campos, um campo para armazenar o código atual de cada chave primária do seu sistema. Assim, toda vez que for incluir um registro, você abre a base de dados com as chaves, bloqueia o registro, pega o valor da chave que você quer, soma +1 (mais um), atualiza o campo com o valor da chave atual, desbloqueia o registro e usa este último valor como a chave para o código. Se, no entanto esta base tiver muitos campos, seu sistema provavelmente utilizará muito a base e alguém pode encontrar seu único registro bloqueado por tempo considerado.

 

Append Blank/DbAppend()

Se você possui no seu sistema um programa em que a inclusão de registros é muito grande em rede, tipo registro de vendas, crie uma função para incluir um registro em branco, tratando o erro, pois um Append Blank/DbAppend() falhará se outro usuário tiver bloqueado o banco de dados ou estiver tentando incluir um registro ao mesmo tempo! Veja como ficaria:

CLI->(APPEND()) // Função para o Append Blank no arquivo CLIENTE (apelidado CLI),
//                             chamando a função desta forma você já seleciona o 
//                             arquivo de alias CLI para a função trabalhar.
// [...] 
FUNCTION APPEND()
DBAPPEND()
DO WHILE NETERR() // Se falhou de novo, fica tentando...
   DBAPPEND()
ENDDO
RETURN

Outra observação importante: Não adianta tentar bloquear o registro (Rlock()) ou usar sua função de bloqueio de registro antes do DbAppend(), pois estaríamos bloqueando o registro corrente e estamos, na verdade, tentando incluir um novo registro pelo sistema, destarte, é apropriada apenas o exemplo acima.

Total votes: 0