Esta é uma mensagem comum e potencialmente frustrante onde supomos que o registro lógico da DataWindow está bloqueado por estar sendo usado em outro local. No PowerBuilder o registro que ele possui está diferente do que está na base. A ideia é que, quando outro usuário atualiza um registro que você já recuperou, você não vai ter a possibilidade de atualizar o mesmo registro sem recupera-lo novamente.
A opção “Where Clause” na “Update Properties” da DataWindow define o grau de bloqueio lógico implementado. Mudar esta propriedade pode fazer o sintoma desaparecer, mudando o controle da DataWindow para um nível mais “liberal” de bloqueio de registro lógico.
Esta pode ser uma solução rápida, mas que pode mascarar o verdadeiro problema: Um erro de lógica que pode trazer outros problemas no futuro. Uma mudança no nível de bloqueio de registro lógico deve ser feito com um planejamento cuidadoso, considerando o impacto da mudança em todo o sistema.
A causa básica desta mensagem é:
- A DataWindow gerou uma instrução UPDATE;
- A cláusula WHERE gerada para a instrução UPDATE não corresponde quaisquer registros no banco de dados;
- A cláusula WHERE é baseada na opção selecionada na caixa de diálogo “Update Properties” e sobre os valores que o DataWindow acredita estão no banco de dados;
Concorrência
A primeira coisa a examinar quando você receber essa mensagem é para garantir que ele realmente não refletem uma questão de concorrência. Coisas para verificar se há conflitos de simultaneidade incluem:
- Outros usuários atualizando as informações na base;
- Outras aplicações batch atualizando informações na base;
- Outras janelas ou processos na mesma instância de sua aplicação: Isto pode ocorrer se você estiver exibindo as mesmas linhas em mais de uma DataWindow (não compartilhada) e então tenta atualizar as duas.
Triggers
Trigger de update e insert que afetem as colunas usadas na cláusula WHERE irão causar este problema. Se uma DataWindow gera um INSERT ou um UPDATE, a DataWindow vai continuar “achando” que os valores dela são os últimos enviados para o banco de dados. A próxima vez que DataWindow gera uma instrução UPDATE para modificar esse registro, ele irá usar esses valores na cláusula WHERE. Se um trigger modificou esses valores, a cláusula WHERE não irá coincidir com o registro.
Existe outra situação onde triggers podem causar este problema. Imagine o seguinte cenário:
- Update na tabela afetando uma linha;
- Existe um trigger de update na tabela.
- Dentro do trigger tenta-se atualizar uma tabela e 0 linhas são encontradas;
- O objeto SQLCA acusará 0 linhas afetadas pela datawindow;
- ERRO: Row Changed between retrieve and update
Neste caso, coloque “SET NOCOUNT ON” nos triggers para SQL Server para resolver problema.
Flags de Status
Esta é a causa mais comum desta mensagem. Se um valor na DataWindow é alterado e o estado é mudado para NotModified através de funções PowerScript, então o novo valor que vai ser utilizado como valor inicial da linha na cláusula WHERE. Outras considerações devem ser dadas a manipulação programática dos flags de status, e o efeito que eles têm sobre o SQL que o DataWindow gera.
O problema mais comum acontece quando os desenvolvedores tentam manipular os flags de status tentando imitar o que o atributo “Initial Values” de uma coluna faz nativamente. Quando valores iniciais sobre uma ou mais colunas são definidos, e uma linha é inserida no DataWindow, esses valores são definidos nas colunas da DataWindow, mas seus flags de status permanecem como NotModified! até que a primeira coluna é mudada.
Nesse ponto, todas as colunas com valores definidos inicialmente são alterados para Modified! de modo que eles são incluídos nas instruções SQL geradas. Usando isso, definir o “Initial Values” no design ou tempo de execução, você pode configurar valores padrão para colunas que, por si, não vão desencadear a geração de uma instrução SQL no Update(), mas serão incluídas se o usuário modifica um campo de modo que o resto da linha requer um INSERT.
Além de simplicidade, esta abordagem tem uma vantagem sobre a manipulação do flag de não influenciar o buffer de valores original, que muitos desenvolvedores farão inadvertidamente.
Latest posts by Breno RdV (see all)
- O que é Metaclass e como ela funciona. (#python #dev #metaclass) - janeiro 11, 2023
- Entenda a mágica dos Generators. (#python, #dev, #generator, #iterator) - dezembro 28, 2022
- Ordenando um DataFrame por múltiplas colunas. (#python #pandas #jupyter #dev #data) - agosto 3, 2022