*
* Verifica se o registro está bloqueado para edição:
* Em caso negativo - bloqueia
* Em caso positivo - mostra uma mensagem e sai
*
IF!EMPR->(DBRLOCK(RECNO()))
EMPR->(DBRLOCK(RECNO()))
ELSE
ALERT('O REGISTRO ESTA EM USO. TENTE MAIS TARDE!!!')
EXIT
ENDIF
*
PegaVariaveis()
*
Edita()
*
GetVariaveis()
*
* Le os dados alterados
READ
*
* Solicita confirmacao atraves da rotina Alerta()
*
if Alerta("Confirma a alteração?","ATENÇÃO",MB_YESNO,MB_ICONQUESTION) == IDYES
* Grava dados
GravaDados()
EMPR->(DBRUNLOCK()) //Libera os registros para uso
EMPR->(DBCOMMIT())
*
endif
*
*
Gostaria, se possível, que alguém disponibilizasse aqui no forum uma pequena rotina a título de exemplo com bloqueio e desbloqueio de registro, inclusive de verificação para ver se tal registro está bloqueado ou não.
Peço isso pq estou "quebrando a cabeça" aqui com um sistema de uso próprio e, até o momento, não conseguí resolver. Tbém não obtive êxito nas buscas que já fiz.
* Verifica se o registro está bloqueado para edição:
* Em caso negativo - bloqueia
* Em caso positivo - mostra uma mensagem e sai
LOCAL lTime := .F.
LOCAL iTime := 0
PegaVariaveis()
Edita()
GetVariaveis()
* Edita Variaveis
READ
* Atualiza varivel
iTime := Seconds()
* Tenta Bloqueio do Registro em Até 2 Segundos
While !( lTime )
* Tenta Bloqueio do Registro
IF EMPR->( DBRLOCK() )
* Sucesso
lTime := .T.
ELSE
* Verifica Limite de Tempo para tentativas...
IF ( ( Seconds() - iTime ) > 2 )
* Tempo Excedido: Abandona loop
EXIT
ENDIF
* Aguarda 1/10 de segundo para nova tentativa
Inkey( 1/10 )
ENDIF
ENDDO
* Se Bloqueou o Registro...
If ( lTime )
* Solicita confirmacao atraves da rotina Alerta()
if Alerta("Confirma a alteração?","ATENÇÃO",MB_YESNO,MB_ICONQUESTION) == IDYES
* Grava dados
GravaDados()
* Salva Arquivo
EMPR->( DBCOMMIT() )
* LIbera registro
EMPR->( DBRUNLOCK() ) //Libera os registros para uso
ELSE
ALERT('O REGISTRO ESTA EM USO. TENTE MAIS TARDE!!!')
ENDIF
* Verifica se o registro está bloqueado para edição:
* Em caso negativo - bloqueia
* Em caso positivo - mostra uma mensagem e sai
LOCAL lTime := .T.
LOCAL iTime := 0
PegaVariaveis()
Edita() // Essa função parece fazer a mesma coisa da proxima: GetVariaveis()
GetVariaveis()
* Edita Variaveis
READ
* Verifica Tecla Escape
If LastKey() # 27
* Solicita confirmacao atraves da rotina Alerta()
if Alerta("Confirma a alteração?","ATENÇÃO",MB_YESNO,MB_ICONQUESTION) == IDYES
* Atualiza varivel
iTime := Seconds()
* Tenta Bloqueio do Registro em Até 2 Segundos
While ( lTime )
* Tenta Bloqueio do Registro
IF EMPR->( DBRLOCK() )
* Grava dados // Parece função desnecessparia
GravaDados()
* Salva Arquivo
EMPR->( DBCOMMIT() )
* LIbera registro
EMPR->( DBRUNLOCK() ) //Libera os registros para uso
ELSE
* Verifica Limite de Tempo para tentativas...
IF ( ( Seconds() - iTime ) > 2 )
* Tempo Excedido: Abandona loop
ALERT('O REGISTRO ESTA EM USO. TENTE MAIS TARDE!!!')
lTime := .F.
ELSE
* Aguarda 1/10 de segundo para nova tentativa
Inkey( 1/10 )
ENDIF
ENDIF
ENDDO
ENDIF
ENDIF
* Tenta Bloqueio do Registro em Até 2 Segundos
While !( lTime )
* Tenta Bloqueio do Registro
IF EMPR->( DBRLOCK() )
* Sucesso
lTime := .T.
ELSE
* Verifica Limite de Tempo para tentativas...
IF ( ( Seconds() - iTime ) > 2 )
* Tempo Excedido: Abandona loop
EXIT
ENDIF
* Aguarda 1/10 de segundo para nova tentativa
Inkey( 1/10 )
ENDIF
ENDDO
* Solicita confirmacao atraves da rotina Alerta()
if Alerta("Confirma a alteração?","ATENÇÃO",MB_YESNO,MB_ICONQUESTION) == IDYES
* Grava dados
GravaDados()
Pois não tem porque eu travar um registro se escolher não confirmar depois.
OPS! LINK QUEBRADO? Veja ESTE TOPICO antes e caso não encontre ENVIE seu email com link do tópico para [url=mailto://fivolution@hotmail.com]fivolution@hotmail.com[/url]. Agradecido.
@braços : ? )
A justiça divina tarda mas não falha, enquanto que a justiça dos homens falha porque tarda.
Também acho que a ordem lógica no código postado está incorreta. Da forma como está, enquanto os gets são lidos algum outro usuário pode alterar o registro e na hora que esta rotina grava, desfaz as alterações do outro usuário.
Creio que a sequencia certa é:
- assim que a alteração for sinalizada, fazer um refresh no registro a alterar ( DbSkip(0) ) e o lock
- receber os novos dados (Gets) enquanto o lock no registro está ativo
- solicitar confirmação da alteração
- se confirmado: - gravar - commit
- unlock
* Verifica se o registro está bloqueado para edição:
* Em caso negativo - bloqueia
* Em caso positivo - mostra uma mensagem e sai
LOCAL lTime := .T.
LOCAL iTime := 0
PegaVariaveis()
Edita() // Essa função parece fazer a mesma coisa da proxima: GetVariaveis()
GetVariaveis()
* Edita Variaveis
READ
* Verifica Tecla Escape
If LastKey() # 27
* Solicita confirmacao atraves da rotina Alerta()
if Alerta("Confirma a alteração?","ATENÇÃO",MB_YESNO,MB_ICONQUESTION) == IDYES
* Atualiza varivel
iTime := Seconds()
* Tenta Bloqueio do Registro em Até 2 Segundos
While ( lTime )
* Tenta Bloqueio do Registro
IF EMPR->( DBRLOCK() )
* Grava dados // Parece função desnecessparia
GravaDados()
* Salva Arquivo
EMPR->( DBCOMMIT() )
* LIbera registro
EMPR->( DBRUNLOCK() ) //Libera os registros para uso
ELSE
* Verifica Limite de Tempo para tentativas...
IF ( ( Seconds() - iTime ) > 2 )
* Tempo Excedido: Abandona loop
ALERT('O REGISTRO ESTA EM USO. TENTE MAIS TARDE!!!')
lTime := .F.
ELSE
* Aguarda 1/10 de segundo para nova tentativa
Inkey( 1/10 )
ENDIF
ENDIF
ENDDO
ENDIF
ENDIF
Agradeço a gentileza e desejo-lhe o mesmo sucesso em suas concepções.
Esse conceito foi muito utilizado e ainda hoje roda em muitos sistemas Clipper.
Querer comparar isso a um SGBD relacional, que é autocontido, gerencia a concorrência, tem controle de transações e integridade referencial e oferece a possibilidade de trabalhar com record sets desconectados é besteira. Mas mesmo assim eles oferecem os recursos de lock de registro, como Select for update (Oracle, DB2, MySql) e Rowlock no SQL Server. Com isso, conforme a necessidade, tem-se a liberdade para ecolher entre bloqueio otimista ou pessimista.
As técnicas que estamos discutindo foram usadas em xBase justamente por seus "bancos de dados" serem apenas amontoados de tabelas e índices, sem os recursos de um SGBD, onde o programador é quem tem que controlar a concorrência.