Concorrencia em Transações
28/09/2004
0
Uso Delphi 7 Enterprise
FireBird 1.5
Componentes IBX - (palheta Interbase)
Windows XP Pro
Thomaz_prg
Posts
28/09/2004
Vinicius2k
Se vc conseguiu com dbExpress, a forma é a mesma, mas NÃO com IBTable...
Use uma IBQuery ou IBDataSet com a instrução SQL +/- assim :
select {lista de campos} from TABELA where CAMPO_CHAVE = VALOR for update with lock
Enquanto o usuário que fizer o primeiro select não commitar a transação dele, o segundo usuário não irá conseguir efetuar updates neste registro.
Configure o IBTransaction com a opção no NOWAIT se quiser q a exceção seja retornada imediatamente.
Bem, vc deve saber q isso se chama travamento pessimista e o nome já diz tudo... é pessimista e na maioria dos casos desnecessário... mas isso depende do contexto da sua aplicação e não posso julgar se no seu caso é necessário ou não...
Sugiro que leia este artigo : http://www.comunidade-firebird.org/cflp/downloads/CFLP_T032.PDF
T+
29/09/2004
Thomaz_prg
E, usando uma IBquery, como ficaria. Agradeço sua ajuda, e peço compreensão, pois, estou tendo que dar manutenção num sistema que não é meu, e como não tenho o hábito de trabalhar com IBX, tenho que perguntar.
Agradeço antecipadamente quem puder me ajudar...
29/09/2004
Vinicius2k
Se vc quer dizer num IBTable, realmente não tem jeito. Infelizmente não existe outra forma. É assim que se faz travamento no IB/FB,
No caso seria melhor utilizar um IBDataSet com a instrução de forma que só retorne um registro... a sua edição, ao invés de ser efetuada na IBTable, seria no IBDataSet e controlando a transação.
Para tentar diminuir sua dificuldade inicial com o IBX, veja este tópico, do colega afarias: http://delphiforum.icft.com.br/forum/viewtopic.php?t=30575
T+
30/09/2004
Thomaz_prg
Vou testar agora e, verei se funciona como quero.
30/09/2004
Thomaz_prg
Bom, fiz exatamente como estava no exemplo do A.Farias, porém, quando abro o sistema 2 vezes, começo a editar um regostro, e no outro, abro para edição o mesmo registro e salvo dá erro.
Acrescentei o que o Vinicius falou. Select * from Clientes where codigo = :cod For Update With Lock, porém ao selecionar um clientes (como no exemplo do A.Farias), ele dá erro. Se tiro a parte do ´for update with lock´ ele funciona. Só que permite que um mesmo registro seja alterado por mais de 1 usuário ao mesmo tempo.
Fico grato a quem puder me ajudar, e grato a quem já ajudou...
Mais uma vez obrigada,
01/10/2004
Thomaz_prg
Ficaria muito agradecido a quem me ajudar.
01/10/2004
Afarias
|para edição (edit) de um registro, se o mesmo já estiver sendo editado
|por outro usuário (travamento pessimista) com os componentes IBX.
Usando IB/FB simplesmente, faça::
Edit;
{
Simule a alteração em algum campo tipo::
FieldByName(´CODIGO´).AsInteger := FieldByName(´CODIGO´).AsInteger;
}
Post;
Pronto! O registro estará travado PARA ALTERAÇÃO até q seja dado um COMMIT ou ROLLBACK (ou seus respectivos ´retainings´)
|quando abro o sistema 2 vezes, começo a editar um regostro, e no
|outro, abro para edição o mesmo registro e salvo dá erro
Exatamente o q vai ocorrer. O erro indica q o registro está ´travado´ e não pode ser alterado -- vc deve tratar essa exceção informando isso ao usuário. Se não quiser isso, vc pode colocar sua transação em WAIT -- mas ai, esteja certo q suas transações sejam curtas ou o usuário vai ficar ´travado´
T+
01/10/2004
Thomaz_prg
Porém que queria que a exceção fosse dada quando eu clicasse no botão com o comando IBDataSet.Edit e não no Post como está acontecendo.
O Vinicius me passou uma dica que até funcionou. O comando
select [campos] from [tabela] for update with lock
só que só funciona se eu tirar o ´FOR UPDATE´. Ou seja, pelo simples fato de selecionar o registro, mesmo que seja para consulta, ele fica bloqueado. Li alguns artigos que dizem que este recurso (FOR UPDATE) está incluso no FB 1.5 (Versão que uso), porém ele não aceita.
Desculpe a insistencia, mas é que tentei (e ainda estou tentando), e estou procurando material na internet, porém não achei nada.
Ficaria muito grato se alguém pudesse me ajudar nesta dúvida. Novamente, obrigado.
01/10/2004
Afarias
|botão com o comando IBDataSet.Edit e não no Post como está
|acontecendo.
:D hehehe... mas olhe com atenção...
se quando for editar, vc vai usar o código::
Edit; FieldByName(´CODIGO´).AsInteger := FieldByName(´CODIGO´).AsInteger; Post; Edit;
Que é para travar o registro. Então, vc terá a exceção exatamente assim q o usuário clicar em EDITAR, não é mesmo?? :wink:
T+
01/10/2004
Thomaz_prg
O caso que estou dizendo é o seguinte:
Na máquina A eu seleciono o Registro 1 e clico em editar (IBDataSet.Edit).
Na máquina B outro usuário seleciona o Registro 1 e clica em editar (IBDataSet.Edit).
No caso, eu queria que quando o comando de edição fosse colocado na máquina B, o usuário recebece uma mensagem do tipo ´Registro sendo alterado em outro terminal´. Mas isto é que não está aocntecendo.
Desculpe mais uma vez a minha insistencia, mas é que realmente estou precisando fazer isso.
Mas uma vez, obrigado.
04/10/2004
Afarias
A solução está ai na sua cara e vc à está despresando. Quando o usuário clicar em algum botão para EDITAR apenas chame o código postado acima.
T+
Clique aqui para fazer login e interagir na Comunidade :)