Editando dados

Editando dados


A regra do Clipper é bloquear o registro antes de gravar os dados, mas observe que há mais coisas entre o céu e a terra do que prega nossa mera filosofia...!

Veja um exemplo:

// o (//) é comentário
// Abertura de arquivo
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
cCODCLI := SPACE(6)
DO WHILE .T.
   CLS
   @ 10,10 SAY "Código do Cliente:" GET cCODCLI VALID EVAL( { || cCODCLI := STRZERO(cCODCLI,6), .T.} ) // Entendeu o valid?! Não? Veja na página de Know-How.
   READ
   IF LASTKEY() = 27 //ESC
      EXIT
   ENDIF
   IF !CLI->(DBSEEK(cCODCLI)) // ! é .NOT.
      ALERT("CODIGO NAO ENCONTRADO")
      LOOP
   ENDIF
   CLI->(DBLOCKREC()) // Função bloqueia o registro em uso (necessário em rede ao alterar registro), veja a função mais abaixo e comentários sobre a posição da mesma. Insira sempre esta função imediatamente antes de disponibilizar os dados p/ alteração.
   cCLI := CLI->NOME
   cEND := CLI->ENDERECO
   // outras variáveis...
   @ 11,10 SAY "CLIENTE:"  GET cCLI
   @ 12,10 SAY "ENDERECO:" GET cEND
   // outros gets...
   READ
   @ 20,10 SAY "CONFIRMA ALTERACAO? (S/N)" GET cSN VALID UPPER(cSN) $ "SN"
   READ
   IF cSN = "N"
      LOOP
   ENDIF
   // Não ponha o CLI->(DBLOCKREC()) aqui! (Veja explicação).
   CLI->NOME     := cCLI
   CLI->ENDERECO := cEND
   CLI->(DBUNLOCK()) // libera o registro p/ uso
   CLI->(DBCOMMIT()) // assegura a integridade do DBF
ENDDO 

...

FUNCTION DBLOCKREC() // Esta função é definida pelo usuário, não é nativa do Clipper!
DO WHILE !RLOCK()
ENDDO
RETURN

Explicação: Você não deve bloquear os registros imediatamente antes de alterar os campos do registro porque você incidirá no problema da atualização perdida. Exemplo: duas estações estão executando o mesmo programa; caso ambas leiam o mesmo registro e introduzam mudanças a serem gravadas, qual será o estado do registro? Que mudanças do usuário foram gravadas? Resposta: As alterações do usuário que gravou pela última vez, a do primeiro se perde, são sobreescritas!

Comentários: O nosso programa acima resolve o problema da atualização perdida, mas já pensou se alguém desse nosso programa começasse a editar um registro e depois se afastasse de sua máquina, digamos, para tomar uns três cafezinhos ou fosse para casa?! Os dados ficariam inacessíveis aos outros por muito tempo!!!

 

Agora veja um exemplo PROFISSIONAL:

Use um campo assinatura

Inclua um campo novo em cada base de dados de seu sistema chamado de assinatura (assinatura, N, 3, 0). Ele existirá apenas para permitir que a codificação da atualização verifique se os campos foram alterados. Veja como ficaria o nosso programa exemplo supracitado reconstruído:

// o (//) é comentário
// Abertura de arquivo
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
cCODCLI := SPACE(6)
DO WHILE .T.
   CLS
   @ 10,10 SAY "Código do Cliente:" GET cCODCLI VALID EVAL( { || cCODCLI := STRZERO(cCODCLI,6), .T.} ) // Entendeu o valid?! Não? Veja na página de Know-How.
   READ
   IF LASTKEY() = 27 //ESC
      EXIT
   ENDIF
   IF !CLI->(DBSEEK(cCODCLI)) // ! é .NOT.
      ALERT("CODIGO NAO ENCONTRADO")
      LOOP
   ENDIF
 
   CLI->(DBLOCKREC())
   CLI->ASSINATURA++
   nASS := ASSINATURA // Representa as informacoes atuais do registro (p/ comparar depois).
   CLI->(DBUNLOCK())
   CLI->(DBCOMMIT())
 
   cCLI := CLI->NOME
   cEND := CLI->ENDERECO
   //outras variáveis...
   @ 11,10 SAY "CLIENTE:" GET cCLI
   @ 12,10 SAY "ENDERECO:" GET cEND
   //outros gets...
   READ
   @ 20,10 SAY "CONFIRMA ALTERACAO? (S/N)" GET cSN VALID UPPER(cSN) $ "SN"
   READ
   IF cSN = "N"
      LOOP
   ENDIF
 
   IF nASS # CLI->ASSINATURA
      ALERT("Registro já alterado por outro usuário, suas alterações serão perdidas!")
      LOOP
   ENDIF
 
   CLI->(DBLOCKREC())
   CLI->NOME := cCLI
   CLI->ENDERECO := cEND
   CLI->ASSINATURA := 0
   CLI->(DBUNLOCK()) // libera o registro p/ uso
   CLI->(DBCOMMIT()) // assegura a integridade do DBF, gravando do Buffer para arquivo.
ENDDO 

Acredite se quiser, mas muitas grandes SoftHouses ainda não fazem isso... FAÇA A DIFERENÇA!!!