Trocando NTX para CDX

Fórum sobre a linguagem CA-Clipper.

Moderador: Moderadores

Jarbas
Usuário Nível 2
Usuário Nível 2
Mensagens: 82
Registrado em: 08 Dez 2005 17:48
Localização: Sao Paulo

Trocando NTX para CDX

Mensagem por Jarbas »

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
Avatar do usuário
gvc
Colaborador
Colaborador
Mensagens: 1270
Registrado em: 23 Ago 2005 10:57

Mensagem por gvc »

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.
Eliane
Usuário Nível 2
Usuário Nível 2
Mensagens: 82
Registrado em: 22 Mai 2006 10:17
Localização: Londrina-PR

Mensagem por Eliane »

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 !
Eliane
Usuário Nível 2
Usuário Nível 2
Mensagens: 82
Registrado em: 22 Mai 2006 10:17
Localização: Londrina-PR

Mensagem por Eliane »

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 ?
Editado pela última vez por Eliane em 29 Set 2006 11:00, em um total de 1 vez.
Avatar do usuário
rochinha
Administrador
Administrador
Mensagens: 4665
Registrado em: 18 Ago 2003 20:43
Localização: São Paulo - Brasil
Contato:

Mensagem por rochinha »

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 :?)
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.
Responder