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!!!
Comentários recentes