Código: MESSAGE Transaction VIEW-AS ALERT-BOX INFO BUTTONS OK. FIND FIRST ITEM EXCLUSIVE-LOCK NO-ERROR. FIND CURRENT ITEM NO-LOCK NO-ERROR. RELEASE ITEM. LEAVE Transaction. MESSAGE TRANSACTION VIEW-AS ALERT-BOX INFO BUTTONS OK. Boa tarde Pessoal alguém sabe como liberar uma transação?
Você precisa delimitar quando começa uma transação e quando termina, segue abaixo o bloco perfeito para se fazer uma transação. Código: DEF TEMP-TABLE ttMsg NO-UNDO /* Tabela para armazenar os erros do sistema, NO-UNDO é essencial para não excluir registros ao desfazer transação */ FIELD Tipo AS INTEGER FIELD Cod AS INTEGER FIELD Msg AS CHAR. /* ##### EXIBE AS MENSAGENS GRAVADAS ######################################################################################### */ PROCEDURE ExibirMensagens. FOR EACH ttMsg NO-LOCK. DEF VAR Mensagem AS CHAR. IF ttMsg.Cod <> 0 THEN Mensagem = "(" + STRING(ttMsg.Cod) + ") - " + ttMsg.Msg. ELSE Mensagem = ttMsg.Msg. IF ttMsg.tipo = 1 THEN DO: /* INFORMAÇÃO */ MESSAGE Mensagem VIEW-AS ALERT-BOX INFO BUTTONS OK TITLE "Informação". END. ELSE IF ttMsg.tipo = 2 THEN DO: /* WARNING */ MESSAGE Mensagem VIEW-AS ALERT-BOX WARNING BUTTONS OK TITLE "Alerta". END. ELSE IF ttMsg.tipo = 3 THEN DO: /* ERRO */ MESSAGE Mensagem VIEW-AS ALERT-BOX ERROR BUTTONS OK TITLE "Erro Crítico". END. END. EMPTY TEMP-TABLE ttMsg. END PROCEDURE. /* ########################################################################################################################## */ /* ####### CRIA UMA NOVA MENSAGEM ########################################################################################### */ PROCEDURE CriaMsg. DEF INPUT PARAMETER vTipo AS INTEGER. DEF INPUT PARAMETER vCod AS INTEGER. DEF INPUT PARAMETER vMsg AS CHAR. CREATE ttMsg. ASSIGN ttMsg.tipo = vTipo ttMsg.cod = vCod ttMsg.Msg = vMsg. END PROCEDURE. /* ########################################################################################################################## */ [FAZER TODAS AS VALIDAÇÕES ANTES DA TRANSAÇÃO, TUDO COM NO-LOCK EXPLÍCITO] DEF VAR EstaOK AS LOGICAL. TMaior: DO TRANS: DO ON QUIT UNDO TMaior, LEAVE: /* ON QUIT E ON STOP FORÇAM O SERVIDOR A DESFAZER SE O SERVIDOR CAIR OU O USUÁRIO PERDER A CONEXÃO */ DO ON STOP UNDO TMaior, LEAVE: DO ON ERROR UNDO TMaior, LEAVE: FIND FIRST minhaTabela WHERE minhaTabela.id = 123456 EXCLUSIVE-LOCK NO-ERROR. /* Bloqueia o registro para alteração */ [Se precisar exibir mensagem, salve na TEMP-TABLE para exibir depois da transação, pois MESSAGE bloqueia a transação e o registro fica bloqueado até alguém clicar na mensagem] IF NOT AVAIL minhaTabela THEN DO: RUN CriaMsg(3,10,"Transação desfeita pois o registro não foi encontrado!"). UNDO TMaior, LEAVE. /* DESFAZ A TRANSAÇÃO (ROLLBACK) e o LEAVE faz pular para o final, não use RETURN */ END. ASSIGN minhaTabela.meuCampo = "ABC". FIND CURRENT minhaTabela NO-LOCK NO-ERROR. /* Libera o registro depois que transação terminar */ EstaOK = TRUE. /* Variável para se verificar que tudo foi realizado com sucesso */ END. END. END. END. IF EstaOK THEN DO: MESSAGE "Sucesso!" VIEW-AS ALERT-BOX INFO BUTTONS OK TITLE "Informação". END. RUN ExibirMensagens. /* Vai exibir todas mensagens que ocorreram dentro da transação */ IMPORTANTE: O código acima foi feito de memória, não verifiquei sintax e pode ter algum erro.
A temp-table ttMsg e as procedures, seria bom colocar numa include pra reutilizar em todos os programas. O Cabeçalho e Rodapé da Transação também poderia ser colocado em Includes, vai de cada gosto. Exemplo: Código: {includes\abrir-transacao.i} [MEU CÓDIGO] {includes\fechar-transacao.i} Onde a include {includes\abrir-transacao.i} teria: TMaior: DO TRANS: DO ON QUIT UNDO TMaior, LEAVE: /* ON QUIT E ON STOP FORÇAM O SERVIDOR A DESFAZER SE O SERVIDOR CAIR OU O USUÁRIO PERDER A CONEXÃO */ DO ON STOP UNDO TMaior, LEAVE: DO ON ERROR UNDO TMaior, LEAVE: e a include {includes\fechar-transacao.i} teria todos os END de cada DO aberto.
Vc não encerra uma transação, mas sim vc pode diminuir o escopo para atender as suas necessidades, ou seja, vc tem que fazer um do transaction: processar o que precisa, e depois do end. a regra do progress é simples, onde ele deduzir que pode haver um IO será um bloco de transação, logico, quando vc não declarar um, se vc declarar do transaction, um dentro do outro, vale o bloco mais externo, então essa regra pode ser problemas em caso de EPC ou UPC, porque vc não sabe se o programa chamador criou já uma transação, então é isso, sempre que possivel, declare um do transaction, faça seu IO dentro desse bloco, mas sempre faça isso no nivel mais detalhado, pra não travar toda a aplicação, porque blocos de transação envolve o fato de que tudo que acontecer dentro desse bloco fica preso, caso aconteça um erro, automaticamente acontece um UNDO, e perde tudo que estava na transação, lembro de um caso, nas primeiras versões do produto EMS2 da datasul, em que tinha um LOG de acesso no menu, eles não cuidaram essa questão, e o bloco de transação ficou ao nivel do menu, usuarios perdiam horas de trabalho porque dava um erro qualquer em um programa e desfazia tudo que tinha processado naquela sessão.