Pessoal, boa tarde, troquei um sistema de NTX para CDX, e estou com o seguinte problema :
- Esta mostrando o mesmo nr. de venda em dois terminais diferentes.
No programa de vendas (balção) , qdo o usuario vai realizar uma venda eu vou no ultimo registro do arquivo , pego o proximo numero , gravo um registro em branco e faço o dbcommit . Isso eu faço já no inicio do programa, depois eu pego todos os dados e no final gravo nesse registro já travado no começo .
Vejam :
dbselectarea("Ven1")
dbgobottom()
lN_Numero:=numero
lN_Numero++
adireg(0) \\Funcao para fazer o append blank e já travar o registro.
field->numero:=lN_Numero
dbunlock()
dbcommit()
O problema é q as vezes aparece o mesmo numero de Venda em dois terminais diferente, qdo eu trabalhava com NTX não tinha esse problema .
Desde já mto obrigado.
Abs
Jarbas
Trocando NTX para CDX
Moderador: Moderadores
Após o dbgobottom(), tente bloquear o registro antes de incluir um novo.
O seu sistema pode estar lendo o ultimo registro para uma máquina e antes de incluir e gravar o próximo registro, outra máquina esta lendo o "ultimo" novamente.
Essa lógica irá provocar problemas quando muitos usuários estiverem entrando com dados.
Veja neste sitio como trabalhar com semaforo.
Boa sorte.
O seu sistema pode estar lendo o ultimo registro para uma máquina e antes de incluir e gravar o próximo registro, outra máquina esta lendo o "ultimo" novamente.
Essa lógica irá provocar problemas quando muitos usuários estiverem entrando com dados.
Veja neste sitio como trabalhar com semaforo.
Boa sorte.
Verifique o seguinte: o index do CDX é CUMULATIVO. Antes de usar o INDEX ON para criar os índices, verifique se o arq.existe:
IF FILE('TESTE.CDX')
DELETE FILE TESTE.CDX
IF FILE('TESTE.CDX')
Mensagem(... O arq. não pode ser deletado ... Verifique...)
ENDIF
ENDIF
Isto para todos os CDX que vc criar. No NTX não precisava disto !
IF FILE('TESTE.CDX')
DELETE FILE TESTE.CDX
IF FILE('TESTE.CDX')
Mensagem(... O arq. não pode ser deletado ... Verifique...)
ENDIF
ENDIF
Isto para todos os CDX que vc criar. No NTX não precisava disto !
Jarbas, outra coisa que pode causar erro é vc pegar o No do último registro DO BANCO DE DADOS e somar 1. Se o indíce estiver corrompido ou desatualizado, ou problemas de gravação simultânea, poderá duplicar dados. Neste site encontrei uma saída segura:
- Crie um arquivo TXT com o No do último registro, ex: CLIENTES.NUM
- Se fosse um sistema seu conteúdo seria: 0000000000
- No seu programa vc irá ler este arquivo, somar 1 e gravar. Assim não haverá maneira de os usuários pegarem o mesmo número. Dê então o ADIREG somente se o usuário confirmar a inserção. Não fique deletando registros em branco. Já fiz isso e não é uma boa saída.
Ex do código :
PROGRAMA CLIENTE
....
....
*** pega ultimo numero de arq.DOS ***
l_utlcod := FNOVOCOD('CLIENTE.NUM')
...
...
*************************************************************
* PROGRAMA : EXPBAIXO
* OBJETIVO : Cadastro em arquivo DOS do numero do ultimo reg.para rede
* - Este arquivo ter apenas o ultimo codigo gravado
* PARAMETROS : pa_arquivo ==> nome do arquivo
* pa_tam ==> tamanho do codigo a ser lido (numerico)
* RETORNO : ultimo codigo ou ZERO se algum erro
******************************************************************************
# include "fileio.ch"
****************************************
FUNCTION FNOVOCOD(pa_arquivo,pa_tam)
****************************************
LOCAL l_handle ,; // handle do arquivo DOS
l_cod ,; // codigo
l_retorno := 0 ,; // 0 se erro ou o codigo lido
l_write ,; // flag de gravacao
l_mensagem ,; // mensagem de erro
l_continua ,; // flag permite continuar mesmo com problemas
l_tela // savescreen
SAVE SCREEN TO l_tela
**** Verifica se arquivo existe
IF ! FILE(pa_arquivo)
l_mensagem := 'Arquivo '+ pa_arquivo + ' nÆo encontrado ! Imposs¡vel inserir ' +;
'registro. Este arquivo cont‚m o No do £ltimo registro !'
l_continua := FRETORNO(l_mensagem)
IF ! l_continua
RESTORE SCREEN FROM l_tela
RETURN(l_retorno)
ENDIF
ENDIF
**** Abre o arquivo ****
l_handle := FOPEN(pa_arquivo,FO_READWRITE+FO_SHARED)
IF FERROR() != 0
l_mensagem := 'Arquivo '+ pa_arquivo + ' nÆo pode ser aberto ! Imposs¡vel inserir ' +;
'registro. Este arquivo cont‚m o No do £ltimo registro !' + ;
'Erro ' + ALLTRIM(STR( FERROR() )) + '.'
l_continua := FRETORNO(l_mensagem)
IF ! l_continua
RESTORE SCREEN FROM l_tela
RETURN(l_retorno)
ENDIF
ENDIF
**** Le codigo/atualiza ****
l_cod := VAL( FREADSTR(l_handle,pa_tam) ) // lˆ o ultimo codigo
l_cod++ // soma 1 ao ultimo codigo
Fseek(l_handle,0) // posiciona comeco do arq.
l_write := Fwrite(l_handle,STRZERO(l_cod,pa_tam), pa_tam )
// l_write retorna o numero de bytes gravados. Se for o mesmo de
// pa_tam porque gravou corretamente
IF l_write <> pa_tam
l_mensagem := 'Erro ' + ALLTRIM(STR( FERROR() )) +' .Problemas na grava‡Æo do No '+;
'do £ltimo registro no arq.' + pa_arquivo + ;
'. NÇO INCLUA NENHUM REGISTRO !!! Reinicie o sistema e verifique ' + ;
'se a numera‡Æo est correta ... '
l_continua := FRETORNO(l_mensagem)
IF ! l_continua
FCLOSE(l_handle)
RESTORE SCREEN FROM l_tela
RETURN(l_retorno)
ENDIF
ENDIF
l_retorno := l_cod // operacao correta
**** Fecha arquivo ****
FCLOSE(l_handle)
// Testa FCLOSE se gravou corretamente, mas mesmo que dˆ erro em fclose
// libera o ultimo numero mas d mensagem ao usuario.
IF FERROR() != 0
NewALERT('Erro ' + ALLTRIM(STR( FERROR() )) + ': Arquivo nÆo pode ser fechado ' +;
'corretamente. NÇO INCLUA REGISTROS. Reinicie o sistema ...' , { 'Retornar'})
ENDIF
RESTORE SCREEN FROM l_tela
RETURN(l_retorno)
*****************************************************************************
* FUNCAO : FRETORNO
* OBJETIVO : Quando acontece um erro com o Arquivo d a chance de
* continuar com senha
* PARAMETROS : pa_mensagem ==> mensagem a exibir
* RETORNO : .f. ou .t.
* --> retorno .t. como entrou com a senha permitir continuar
* --> para tentar arrumar o problema com o arquivo
******************************************************************************
STATIC FUNCTION FRETORNO(pa_mensagem)
*****************************************
LOCAL l_botao ,; // No do botao escolhido em newalert
l_senha ,; // senha
l_resp := .f. // retorno .t. se continua mesmo com erro
l_botao := NEWALERT(pa_mensagem,{ ' Retornar ' , ' SENHA ' })
IF l_botao = 2
NEWMENSA(' Entre com a Senha de DOS-Dbf ou <ENTER> para Sair : ')
@ 13,22 SAY "SENHA .......: "
l_senha := DIG_SEN(13,37,0)
IF l_senha = "DOS_EXP"
l_resp := .t.
ENDIF
ENDIF
RETURN(l_resp)
Pergunta: Gostaria de mandar o código com identação (tabulação) para ficar mais fácil de compreender. Não sei mexer direito neste editor do fórum. Poderia me explicar ?
- Crie um arquivo TXT com o No do último registro, ex: CLIENTES.NUM
- Se fosse um sistema seu conteúdo seria: 0000000000
- No seu programa vc irá ler este arquivo, somar 1 e gravar. Assim não haverá maneira de os usuários pegarem o mesmo número. Dê então o ADIREG somente se o usuário confirmar a inserção. Não fique deletando registros em branco. Já fiz isso e não é uma boa saída.
Ex do código :
PROGRAMA CLIENTE
....
....
*** pega ultimo numero de arq.DOS ***
l_utlcod := FNOVOCOD('CLIENTE.NUM')
...
...
*************************************************************
* PROGRAMA : EXPBAIXO
* OBJETIVO : Cadastro em arquivo DOS do numero do ultimo reg.para rede
* - Este arquivo ter apenas o ultimo codigo gravado
* PARAMETROS : pa_arquivo ==> nome do arquivo
* pa_tam ==> tamanho do codigo a ser lido (numerico)
* RETORNO : ultimo codigo ou ZERO se algum erro
******************************************************************************
# include "fileio.ch"
****************************************
FUNCTION FNOVOCOD(pa_arquivo,pa_tam)
****************************************
LOCAL l_handle ,; // handle do arquivo DOS
l_cod ,; // codigo
l_retorno := 0 ,; // 0 se erro ou o codigo lido
l_write ,; // flag de gravacao
l_mensagem ,; // mensagem de erro
l_continua ,; // flag permite continuar mesmo com problemas
l_tela // savescreen
SAVE SCREEN TO l_tela
**** Verifica se arquivo existe
IF ! FILE(pa_arquivo)
l_mensagem := 'Arquivo '+ pa_arquivo + ' nÆo encontrado ! Imposs¡vel inserir ' +;
'registro. Este arquivo cont‚m o No do £ltimo registro !'
l_continua := FRETORNO(l_mensagem)
IF ! l_continua
RESTORE SCREEN FROM l_tela
RETURN(l_retorno)
ENDIF
ENDIF
**** Abre o arquivo ****
l_handle := FOPEN(pa_arquivo,FO_READWRITE+FO_SHARED)
IF FERROR() != 0
l_mensagem := 'Arquivo '+ pa_arquivo + ' nÆo pode ser aberto ! Imposs¡vel inserir ' +;
'registro. Este arquivo cont‚m o No do £ltimo registro !' + ;
'Erro ' + ALLTRIM(STR( FERROR() )) + '.'
l_continua := FRETORNO(l_mensagem)
IF ! l_continua
RESTORE SCREEN FROM l_tela
RETURN(l_retorno)
ENDIF
ENDIF
**** Le codigo/atualiza ****
l_cod := VAL( FREADSTR(l_handle,pa_tam) ) // lˆ o ultimo codigo
l_cod++ // soma 1 ao ultimo codigo
Fseek(l_handle,0) // posiciona comeco do arq.
l_write := Fwrite(l_handle,STRZERO(l_cod,pa_tam), pa_tam )
// l_write retorna o numero de bytes gravados. Se for o mesmo de
// pa_tam porque gravou corretamente
IF l_write <> pa_tam
l_mensagem := 'Erro ' + ALLTRIM(STR( FERROR() )) +' .Problemas na grava‡Æo do No '+;
'do £ltimo registro no arq.' + pa_arquivo + ;
'. NÇO INCLUA NENHUM REGISTRO !!! Reinicie o sistema e verifique ' + ;
'se a numera‡Æo est correta ... '
l_continua := FRETORNO(l_mensagem)
IF ! l_continua
FCLOSE(l_handle)
RESTORE SCREEN FROM l_tela
RETURN(l_retorno)
ENDIF
ENDIF
l_retorno := l_cod // operacao correta
**** Fecha arquivo ****
FCLOSE(l_handle)
// Testa FCLOSE se gravou corretamente, mas mesmo que dˆ erro em fclose
// libera o ultimo numero mas d mensagem ao usuario.
IF FERROR() != 0
NewALERT('Erro ' + ALLTRIM(STR( FERROR() )) + ': Arquivo nÆo pode ser fechado ' +;
'corretamente. NÇO INCLUA REGISTROS. Reinicie o sistema ...' , { 'Retornar'})
ENDIF
RESTORE SCREEN FROM l_tela
RETURN(l_retorno)
*****************************************************************************
* FUNCAO : FRETORNO
* OBJETIVO : Quando acontece um erro com o Arquivo d a chance de
* continuar com senha
* PARAMETROS : pa_mensagem ==> mensagem a exibir
* RETORNO : .f. ou .t.
* --> retorno .t. como entrou com a senha permitir continuar
* --> para tentar arrumar o problema com o arquivo
******************************************************************************
STATIC FUNCTION FRETORNO(pa_mensagem)
*****************************************
LOCAL l_botao ,; // No do botao escolhido em newalert
l_senha ,; // senha
l_resp := .f. // retorno .t. se continua mesmo com erro
l_botao := NEWALERT(pa_mensagem,{ ' Retornar ' , ' SENHA ' })
IF l_botao = 2
NEWMENSA(' Entre com a Senha de DOS-Dbf ou <ENTER> para Sair : ')
@ 13,22 SAY "SENHA .......: "
l_senha := DIG_SEN(13,37,0)
IF l_senha = "DOS_EXP"
l_resp := .t.
ENDIF
ENDIF
RETURN(l_resp)
Pergunta: Gostaria de mandar o código com identação (tabulação) para ficar mais fácil de compreender. Não sei mexer direito neste editor do fórum. Poderia me explicar ?
Editado pela última vez por Eliane em 29 Set 2006 11:00, em um total de 1 vez.
- rochinha
- Administrador

- Mensagens: 4665
- Registrado em: 18 Ago 2003 20:43
- Localização: São Paulo - Brasil
- Contato:
Amiguinho
Faça uso da função de uso geral que coloquei na sessão código fonte.
Com ela será praticamente impossivel voce obter um contador duplicado para qualquer arquivo controlado.
https://pctoledo.org/forum/viewto ... =5952#5952
@braços :?)
Faça uso da função de uso geral que coloquei na sessão código fonte.
Com ela será praticamente impossivel voce obter um contador duplicado para qualquer arquivo controlado.
https://pctoledo.org/forum/viewto ... =5952#5952
@braços :?)
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.
@braços : ? )
A justiça divina tarda mas não falha, enquanto que a justiça dos homens falha porque tarda.

