Página 2 de 2

Condigo Sequencial

Enviado: 14 Mai 2015 07:25
por Josmar dos Santos

Código: Selecionar todos

 FUNCTION SALVAR02(TIPO_ACAO)
02	LOCAL IRetorno := .F.
03	IF TIPO_ACAO = INCLUSAO
04	   CLIENTES->(Dbappend())
05	   cCODIGO := alltrim( STRZERO( PSQCONTROLE( "clientes" ), 5 ))
06	   if cCODIGO="00000"
07	      ALERT("Ocorreu um erro na efetiva‡Æo do CODIGO SEQUENCIAL")
08	      RETURN .F.
09	   ENDIF
10	   CLIENTES->CODIGO := cCODIGO
11	   ALERT("Numero gerado no arquivo: " +cCODIGO)
12	ELSE
13	   CLIENTES->(RLOCK() )
14	ENDIF
15	IF .NOT. NETERR()
51	   CLIENTES->( DBCOMMIT() )
52	   CLIENTES->( DBUNLOCK() )
53	ELSE
54	   ALERT("Falha ao incluir novo cliente")
55	endif
56	return .t.  

Bom dia Rochinha. Estou usando essa mesma rotina para gerar o código sequencial com a sua função PsqControle. O código não voltou aos valores anteriores como eu já havia mencionado acima, mas não está pulando, ou seja, ele registra por exemplo: sempre o valor 33.000.

Deu erro de sintaxe nesse comando:
DEFAULT _altera_ := .t., _ComValor_ := 0
Para mim dentro da minha ignorância está correto, mas o compilador não gostou.
É pessoal, admiro vocês que já estão na estrada a tando tempo porque confesso a vocês, não está sendo fácil para mim!!!! , mas sou Brasileiro não desisto nunca...rs.rs.rs.rs
:%

Josmar

Condigo Sequencial

Enviado: 14 Mai 2015 10:52
por JoséQuintas
Se olhar direito, a pesqcontrole inicia a contagem com RecCount() + RecCount() / 4
Isso vai ser 50% a mais do que a quantidade de registros.

Se olhar direito também, não pode usar REPLACE direto, já que a rotina pode falhar e retornar valor zero, ou até esse número acima em determinada situação.

Tem que considerar que a rotina é exemplo, não é só colocar no seu programa e pronto.
Tem que ajustar pra suas rotinas de rede, pra considerar falhas no programa que usa a rotina, etc.
Até mesmo conflito de nome de variáveis usadas na rotina.

Tá aqui uma versão mais próxima do que eu uso:

Código: Selecionar todos

FUNCTION ProximoCodigo( cDbf, lSeek )
   LOCAL nCodigo, nSelect, acStructure

   nSelect := Select() // salva a área atual
   lSeek   := iif( lSeek == NIL, .T., lSeek )

   IF Select( "CONTROLE" ) == 0
      IF .NOT. File( "CONTROLE.DBF" )
         acStructure := { { "DATABASE" , "C", 12, 0 } , { "CONTADOR" , "N", 10, 0 } } // pra que economizar. Deixa tamanho 10 e tá pronto pro futuro
         SELECT 0 // só por garantia
         dbCreate( "CONTROLE", acStructure )
      ENDIF
      SELECT 0
      USE CONTROLE SHARED
   ENDIF

   SELECT ( Select( "CONTROLE" ) ) // SELECT é comando, e Select() é função
   LOCATE FOR UPPER( controle->Database ) = UPPER( cDbf )
   IF Eof()
      APPEND BLANK
      REPLACE controle->Database WITH cDBF, controle->Contador WITH 1
      SKIP 0
      UNLOCK
   ENDIF
   DO WHILE .NOT. RLock()
      InKey(0.5) // aguarde, não vai querer travar o computador ou sobrecarregar a rede tentando bloquear o registro
   ENDDO
   SKIP 0 // depois que conseguiu bloquear o registro, atualiza informação pra ver se mudou
   nCodigo := controle->Contador
    IF lSeek // se é pra pesquisar se existe, então pesquisa
      SELECT ( nSelect )
      DO WHILE .T.
         SEEK nCodigo
         IF Eof()
            EXIT // se não existe, então achou código disponível
         ENDIF
         nCodigo += 1
      ENDDO
   ENDIF
   SELECT CONTROLE
   REPLACE controle->Contador WITH nCodigo + 1 // deixa gravado como disponível o seguinte, e não o que vai usar agora
   SKIP 0 // antes de liberar, deixa atualizado
   UNLOCK // ok, atualizado libera, antes disto não, porque primeiro tem que achar o código e ter certeza de que ninguém mais vai usar
   SELECT ( nSelect )
   RETURN nCodigo // ok, aqui é o atual que não existe
Notas:
- Não usava COMMIT no Clipper, e continuo não usando no Harbour.
- Usando ou não o código retornado, ele vai ser desprezado, então pode acontecer de pular um número.
- Montei a rotina na hora de postar, apenas como exemplo, revise, só usei compilação -w3 -es2 pra não errar nomes de variáveis.
- Estou considerando que está usando Clipper 5.x
- Não se esqueça de passar .F., caso não queira confirmação de registro já existente

A idéia é: pega o próximo número, com a opção de verificar no arquivo original se já existe, mas o arquivo original precisa estar indexado por essa chave, e precisa ser numérica (a não ser que altere esta rotina).

Condigo Sequencial

Enviado: 16 Mai 2015 02:49
por Josmar dos Santos
Fiz algumas alterações na função inserindo alguns comandos de redes e o mesmo já está funcionando. Agora aguardar alguns dias para ver se não vai dar problemas...obrigado a todos


Josmar


:{

Código Sequencial

Enviado: 16 Mai 2015 09:47
por JoséQuintas
Faltou eu dizer:

No tempo do Clipper, eu NÃO usava o arquivo de controle de numeração.
Era raro ter problema - talvez 2 vezes num ano.
Usava BOTO BOTTOM, Codigo = Ultimo + 1
Mas também a rotina do SEEK, pra confirmar se estava em uso.

Quando passei pro Harbour, tive que usar o arquivo de controle.

Ao acontecer isso na migração pra Harbour, a primeira coisa é pensar no Harbour fazendo errado.
Mas se pega o último + 1, devia ser comum número repetido com muitos usuários fazendo inclusão.
Hoje em dia me pergunto como é que isso funcionava no Clipper sem o arquivo de controle.

Condigo Sequencial

Enviado: 17 Mai 2015 01:29
por rochinha
Amiguinhos,

Só complementando, o SET DEFAULT é uma melhoria na facilidade de criticar os parâmetros passados pelas funções.

Um Set Default critica equivale a iif( critica, RetornaAlgoComoSendoPadrao, RetornaOValorDoParamentroPassado ).

Condigo Sequencial

Enviado: 17 Mai 2015 07:31
por JoséQuintas
O rochinha deve estar se referindo ao comando DEFAULT
Se não me engano, ele é definido num #include, e apenas facilita digitação, já que é substituído pelo iif().
Usando uma função, reduz código e reduz o EXE.

Código: Selecionar todos

Default( @variavel, 5 )

FUNCTION Default( xVariavel, xValor )
   xVariavel := iif( xVariavel == NIL, xValor, xVariavel )
Pode até criar com o mesmo nome existente no Harbour, assim já acostuma pra quando trocar.

Condigo Sequencial

Enviado: 19 Mai 2015 10:06
por Eolo
Quando passei pro Harbour, tive que usar o arquivo de controle.

Ao acontecer isso na migração pra Harbour, a primeira coisa é pensar no Harbour fazendo errado. Mas se pega o último + 1, devia ser comum número repetido com muitos usuários fazendo inclusão. Hoje em dia me pergunto como é que isso funcionava no Clipper sem o arquivo de controle.
Eu sempre usei (e ainda uso) o “último + 1”, no Clipper e no Harbour, mas embaixo de um Flock(), e nunca tive nenhum problema com chaves repetidas, só com “gargalos” no processamento (ver abaixo).

Como exemplo, tive um cliente, uma loja de materiais de construção, 6 terminais emitindo pedidos ao mesmo tempo, isso no Summer e NTX: cada usuário entrava com os dados do pedido (ainda sem a chave = o número do pedido) e, na hora de gravar, eu rodava o Flock(), gerava e gravava a próxima chave, COMMIT e aí liberava o DBF pra um próximo usuário / chave. Isso feito, ia gravar os demais dados do pedido, agora com o Rlock(). Gargalo? Sim, o DBF ficava “Flockado” por coisa de 2 segundos...

Um preço (em tempo) barato pra nunca ter problemas com chaves.

Enfim, pode não ser a maneira tecnicamente mais avançada de fazer a coisa, mas pra mim sempre resolveu e continua resolvendo.