Nesse vídeo demonstraremos em como ativar o controle de transações no banco de dados através dos comandos Begin Transaction e End Transaction.
Abaixo o código fonte desenvolvido para o exemplo em vídeo acima:
//Bibliotecas
#Include "TOTVS.ch"
/*/{Protheus.doc} User Function zExe065
Exemplo de como realizar gravações, mas em caso de falha seja abortado
@type Function
@author Atilio
@since 06/12/2022
@see https://tdn.totvs.com/display/public/framework/BEGIN+TRANSACTION
@obs
**** Apoie nosso projeto, se inscreva em https://www.youtube.com/TerminalDeInformacao ****
/*/
User Function zExe065()
Local aArea := FWGetArea()
//Iniciando controle de transações
Begin Transaction
//Inclui um novo produto
RecLock('SBM', .T.)
SBM->BM_GRUPO := "TST1"
SBM->BM_DESC := "Teste " + Time()
SBM->(MsUnlock())
//Se a pergunta foi confirmada, cancela os lançamentos na transação
If FWAlertYesNo("Deseja cancelar e disarmar a transação?", "Atenção")
DisarmTransaction()
EndIf
//Finalizando controle de transações
End Transaction
FWRestArea(aArea)
Return
Bom pessoal, por hoje é só.
Abraços e até a próxima.
Olá, Daniel!
Existe alguma forma de eu utilizar o controle de transações ou alguma outra tratativa que armazene as alterações que eu quero realizar no banco em cash, para só após a finalização do laço de fato executar todas as inserções?
Begin Transaction
While SZ6->(!Eof()) .And. SZ6->Z6_PRODUTO == SZ7->Z7_PRODUTO .And. Alltrim(SZ6->Z6_CAIXA) == Alltrim(cCxNova)
RecLock(“SZ6”,.F.)
SZ6->Z6_PEDIDO := (cAliasTMP)->XX_PEDIDO
SZ6->Z6_TSEPARA := cTipo
If cCtrlMac == ‘S’
SZ6->Z6_PEDREM:= cPedRem
EndIf
If nCont > nBipPend
DisarmTransaction()
Return .F.
EndIf
MsUnLock()
SZ6->(DbSkip())
End
End Transaction
O que acontece nesse código é na verdade o cancelamento da alteração da linha corrente caso caia no If após o reclock. Mas o que eu pretendia que acontecesse é que ele cancelasse todas as alterações visto o fato de o laço estar dentro da estrutura de controle de transação.
Bom dia Arthur, tudo joia?
Sim, o próprio controle de transações já faz isso, mas você não pode encerrar ele no meio (como com esse return .F. no meio do processo).
O que você precisa fazer, é controlar por exemplo, numa variável, e no fim da transação você valida. Ai o laço, você interrompe ele com um Exit, algo +- assim:
//Inicia o controle de transações Begin Transaction lDeuCerto := .T. //Faz o laço While SZ6->(!Eof()) .And. SZ6->Z6_PRODUTO == SZ7->Z7_PRODUTO .And. Alltrim(SZ6->Z6_CAIXA) == Alltrim(cCxNova) //Valida se há divergência, se sim, sai do laço If nCont > nBipPend lDeuCerto := .F. Exit EndIf //Atualiza as informações RecLock("SZ6", .F.) //aqui você grava seus campos SZ6->(MsUnlock()) SZ6->(DbSkip()) EndDo //Se deu certo, efetiva a transação If lDeuCerto DbCommitAll() //Senão, cancela a transação e aborta tudo que foi alterado Else DisarmTransaction() EndIf End TransactionTenha uma ótima e abençoada quinta feira.
Um forte abraço.
Opa, bom dia, Daniel!
Obrigado pela resposta rápida, mas seguindo a estrutura que você passou ainda assim não funcionou como eu gostaria meu amigo.
Begin Transaction
nContBip := oApont:aCols[nPosProd][5]
While SZ6->(!Eof()) .And. SZ6->Z6_PRODUTO == SZ7->Z7_PRODUTO .And. Alltrim(SZ6->Z6_CAIXA) == Alltrim(cCxNova)
If ++nContBip > oApont:aCols[nPosProd][3]
lCxCAceita := .F.
Exit
EndIf
RecLock(“SZ6″,.F.)
SZ6->Z6_PEDIDO := (cAliasTMP)->XX_PEDIDO
SZ6->Z6_TSEPARA := cTipo
If cCtrlMac == ‘S’
SZ6->Z6_PEDREM:= cPedRem
EndIf
MsUnLock()
SZ6->(DbSkip())
End
If lCxCAceita
DbCommitAll()
Else
DisarmTransaction()
EndIf
End Transaction
If !lCxCAceita
MsgLogErr(Time() + ” – Caixa Coletiva ” + cCxBip + ” já possui alguns NS em uso. Necessário bipar individual.” + chr(13)+chr(10))
Return .F.
EndIf
No bloco acima, adaptei para a estrutura que você recomendou mas ao rodar debugando, vi que ele entra na condição de saída, realiza o Exit, executa o disarm() e mesmo assim os dados continuam preenchidos no banco. Posicionei o return fora do controle de transação.
Bom dia Arthur, tudo joia?
Nós que agradecemos o feedback.
Infelizmente nunca passei por esse cenário, sempre que rodei o DisarmTransaction(), ele cancelava todas as operações feitas no banco de dados.
Você consegue fazer um teste? Pegar o mesmo trecho e testar em um cliente diferente com banco de dados diferente? Pois, a minha suposição, vai que no banco de dados, esteja alguma configuração de “auto commit” após a realização de atualizações.
Tenha uma ótima e abençoada sexta feira.
Um forte abraço.