Controle de lock.
Boma Dia, como vocês fazem para 2 usuários não digitarem o mesmo código em um cadastro por exemplo.
Criam uma tabela de lock com uma chave do usuário e o nome do programa ?
Criam uma tabela de lock com uma chave do usuário e o nome do programa ?
Lynx
Curtidas 0
Respostas
Khundalini
18/07/2005
Não vejo uma alternativa melhor que o evento OnReconcileError do TClientDataSet pra resolver uma questão como essa!
[]s
Rubem Rocha
Manaus, AM
[]s
Rubem Rocha
Manaus, AM
GOSTEI 0
Lynx
18/07/2005
eu só uso TQuery em cadastros...
GOSTEI 0
Lynx
18/07/2005
se eu entendi bem, vou colocar um datasource ligado com um dataset...
e minha query liga com o DataSource.
Este evento funciona como ?
na hora do código, quando sai ?
ou na hora que inseri.
obrigado.
e minha query liga com o DataSource.
Este evento funciona como ?
na hora do código, quando sai ?
ou na hora que inseri.
obrigado.
GOSTEI 0
Titanius
18/07/2005
Na seção Artigos do Clube Delphi, tem um Sequenciador, muito bom, utilizo ele, e nunca deu um problema comigo...
[]s
[]s
GOSTEI 0
Lynx
18/07/2005
O ID, da tabela eu utilizo trigger no delphi com generatores....
O Código é digitado, então nao vejo problema, no sequenciador para o ID da tabela.
No artigo mostra que tem problema, não sei se entendi direito.
obrigado
O Código é digitado, então nao vejo problema, no sequenciador para o ID da tabela.
No artigo mostra que tem problema, não sei se entendi direito.
obrigado
GOSTEI 0
Titanius
18/07/2005
eh, comigo nunca deu problema, mas o codigo eh gerado e nao digitado, como o seu caso....
GOSTEI 0
Lynx
18/07/2005
o ID da tabela é gerado...
O Código é digitado...
por isso estou preocupado, pq pode acontecer , que 2 usuários estao no mesmo código...
O Código é digitado...
por isso estou preocupado, pq pode acontecer , que 2 usuários estao no mesmo código...
GOSTEI 0
Adriano Santos
18/07/2005
Tenho usado Triggers e Generator nos meus programas e não tenho tido problemas com eles.
GOSTEI 0
Lynx
18/07/2005
asrsantos, você usa a trigger para o id , e o codigo é digitado certo ?
Deste modo eu tb n tenho problemas...
mas vc controla como para 2 usuários não digitar o mesmo código nos terminais ?
valeu
Deste modo eu tb n tenho problemas...
mas vc controla como para 2 usuários não digitar o mesmo código nos terminais ?
valeu
GOSTEI 0
Adriano Santos
18/07/2005
As tabelas dos meus programas eu uso um campo ID que eu deixo o banco controlar através das triggers e dos generators, e ai se necessário eu crio um campo Código para que o usuário utilize para identificar algo, como uma tabela de produtos por exemplo. Para que o usuário não digite o código de um produto igual a de outro eu faço uma pesquisa no banco com uma Query simples. Se o código já existir eu aviso o usuário e obrigo cadastrar um novo código.
Se entendi direito o que precisa, é isso. Não tem segredo.
Se entendi direito o que precisa, é isso. Não tem segredo.
GOSTEI 0
Lynx
18/07/2005
isso eu também faço , exemplo vou cadastrar um produto com o código 20, e ao mesmo tempo outro usuário em outro terminal coloca o código 20, enquanto o terminal 1 ainda está digitando o produto..
entende ?
se ele ainda nao deu um commit...
como você controla está situação ?
entende ?
se ele ainda nao deu um commit...
como você controla está situação ?
GOSTEI 0
Adriano Santos
18/07/2005
Agora entendi direito sua dúvida.
Bom, este é um caso típico e acontece muito haja vista que não é possível saber o que cada usuário está digitando em cada terminal. Mas uma coisa é certa, a probabilidade de dois terminais dar um commit ao mesmo tempo é remota, ou seja, se fizer uma nova pesquisa no banco de dados antes do post vc consegue saber se o código já existe.
Normalmente eu faço duas pesquisas.
1 - Quando o usuário sai do campo onde deve digitar o código do produto, cliente etc.
2 - No momento de dar um post. Isso evita que: durante a digitação de um novo cliente, por exemplo, outro usuário entre e coloque o mesmo código de cliente. Se isso ocorreu dou uma mensagem e o cara vai ter que colocar outro código, ai então faço o commit.
Bom, este é um caso típico e acontece muito haja vista que não é possível saber o que cada usuário está digitando em cada terminal. Mas uma coisa é certa, a probabilidade de dois terminais dar um commit ao mesmo tempo é remota, ou seja, se fizer uma nova pesquisa no banco de dados antes do post vc consegue saber se o código já existe.
Normalmente eu faço duas pesquisas.
1 - Quando o usuário sai do campo onde deve digitar o código do produto, cliente etc.
2 - No momento de dar um post. Isso evita que: durante a digitação de um novo cliente, por exemplo, outro usuário entre e coloque o mesmo código de cliente. Se isso ocorreu dou uma mensagem e o cara vai ter que colocar outro código, ai então faço o commit.
GOSTEI 0
Adriano Santos
18/07/2005
...que colocar outro código, ai então faço o commit....
Claro, só posso dar um commit se o caso for negativo, ou seja, se o código não existe na tabela.
GOSTEI 0
Lynx
18/07/2005
desculpe asrsantos, realmente eu expressei mau minha pergunta...
Vou fazer isso também, mas o complicado se eu dar o focu,no campo código eu estou fazendo limpar toda minha tela...
acho que vou dar uma mensagem avisando que o código já existe, e que o código vai ser um número acima que ele digitou.
exemplo:
Usuário 1, está digitando uma nota número 1, ao mesmo tempo o usuário 2 está digitando a nota 1 também...
Mas o usuário 2 deu um commit primeiro, então quando o usuário 1 dar o post.
Vou enviar uma mensagem avisando que o número 1, já existe e a nota dele será o número 2.
O Que você acha disso ?
obrigado
valeu
Vou fazer isso também, mas o complicado se eu dar o focu,no campo código eu estou fazendo limpar toda minha tela...
acho que vou dar uma mensagem avisando que o código já existe, e que o código vai ser um número acima que ele digitou.
exemplo:
Usuário 1, está digitando uma nota número 1, ao mesmo tempo o usuário 2 está digitando a nota 1 também...
Mas o usuário 2 deu um commit primeiro, então quando o usuário 1 dar o post.
Vou enviar uma mensagem avisando que o número 1, já existe e a nota dele será o número 2.
O Que você acha disso ?
obrigado
valeu
GOSTEI 0
Adriano Santos
18/07/2005
Acho boa a idéia. A única coisa
Outra forma, talvez menos eficaz e ou menos ´profissional´, seria criar uma lista de códigos que estão sendo digitados no momento. Por exemplo:
Você tem os terminais 1, 2 e 3. Quando cada terminar entrar e digitar um código vc alimenta uma tabela dentro do banco que será usada só pra isso. E na hora que um novo usuário entrar para digitar o codigo vc pesquisa nessa tabela. Se o codigo existir vc pede outro, senão mantem o codigo e atualiza esta tabela.
Quando o usuario der um post ou cancel, vc faz o commit e exclui este codigo da lista.
Tive esta idéia agora (do nada, rs), não é muito prática, mas dependendo do caso acredito que funcione.
É só uma idéia esdruxula que me passou pela cabeça.
Outra forma, talvez menos eficaz e ou menos ´profissional´, seria criar uma lista de códigos que estão sendo digitados no momento. Por exemplo:
Você tem os terminais 1, 2 e 3. Quando cada terminar entrar e digitar um código vc alimenta uma tabela dentro do banco que será usada só pra isso. E na hora que um novo usuário entrar para digitar o codigo vc pesquisa nessa tabela. Se o codigo existir vc pede outro, senão mantem o codigo e atualiza esta tabela.
Quando o usuario der um post ou cancel, vc faz o commit e exclui este codigo da lista.
Tive esta idéia agora (do nada, rs), não é muito prática, mas dependendo do caso acredito que funcione.
É só uma idéia esdruxula que me passou pela cabeça.
GOSTEI 0
Lynx
18/07/2005
com certeza asrsantos, esse é o típico lock, que eu coloquei no tópico.
O Sistema na empresa onde eu trabalhava, cada form que abria grava em uma tabela chamada lock.
A chave da tabela lock era o usuário, tinha o nome do form, e o código.
Funcionava legal, mas quando travava o micro algo parecido, ficava preso no lock e não logava mais :lol: .
Fizeram outro programa para apagar o lock, era um ´xunxo´.
Mas está sua idéia da pesquisa antes do commit é o ideal mesmo.
Mas este lock, da para saber onde o usuário está no sistema... fazer aparecer online etc.
Mas ainda acho que a melhor maneira é está da pesquisa antes do commit.
Valeu
O Sistema na empresa onde eu trabalhava, cada form que abria grava em uma tabela chamada lock.
A chave da tabela lock era o usuário, tinha o nome do form, e o código.
Funcionava legal, mas quando travava o micro algo parecido, ficava preso no lock e não logava mais :lol: .
Fizeram outro programa para apagar o lock, era um ´xunxo´.
Mas está sua idéia da pesquisa antes do commit é o ideal mesmo.
Mas este lock, da para saber onde o usuário está no sistema... fazer aparecer online etc.
Mas ainda acho que a melhor maneira é está da pesquisa antes do commit.
Valeu
GOSTEI 0
Titanius
18/07/2005
amigo lynx, tenho um codigo aqui, talvez vc possa melhora-lo:
Basicamente, verifico se o numero jah existe, se existe eu modifico e informo ao usuario...
[]s
if (SPGEN <> nil) then begin
if ((DataSource as TDatasource).DataSet as TIBDataset).State = dsInsert then begin
(SPGEN as TIBStoredProc).ParamByName(´INCREMENTO´).AsInteger := 1;
(SPGEN as TIBStoredProc).ExecProc;
if (SPGEN as TIBStoredProc).ParamByName(´VALOR´).AsInteger <> (StrToInt((EditChave[0] as TEdit).Text) + 1) then begin
(EditChave[0] as TEdit).Text := StrZero(IntToStr((SPGEN as TIBStoredProc).ParamByName(´VALOR´).AsInteger - 1), 5);
((DataSource as TDatasource).DataSet as TIBDataset).FieldByName(copy((EditChave[0] as TEdit).Name, 3, length((EditChave[0] as TEdit).Name) - 2)).AsString := (EditChave[0] as TEdit).Text;
Application.MessageBox(PChar(´O código foi alterado para ´ + (EditChave[0] as TEdit).Text), ´Atenção...´, 0);
end;
end;
end;
try
((DataSource as TDatasource).DataSet as TIBDataset).Post;
if ((DataSource as TDatasource).DataSet as TIBDataset).CachedUpdates then
((DataSource as TDatasource).DataSet as TIBDataset).ApplyUpdates;
((DataSource as TDatasource).DataSet as TIBDataset).Close;
{Se Tag do transaction for <> 0 não commita}
if (((DataSource as TDataSource).DataSet as TIBDataSet).Transaction as TIBTransaction).Tag = 0 then
(((DataSource as TDataSource).DataSet as TIBDataSet).Transaction as TIBTransaction).Commit;
Result := True;
except
(SPGEN as TIBStoredProc).ParamByName(´INCREMENTO´).AsInteger := -1;
(SPGEN as TIBStoredProc).ExecProc;
Result := False;
end;
Basicamente, verifico se o numero jah existe, se existe eu modifico e informo ao usuario...
[]s
GOSTEI 0
Lynx
18/07/2005
Titanius, obrigado pelo código, assim que eu terminar os cadastros do sistema, (tem 7 grandes) vou começar a fazer este controle.
Valeu
Valeu
GOSTEI 0
Adriano Santos
18/07/2005
Realmente Lynx, você tem razão. Se ocorre qualquer problema com um usuário o ´lock´ fica preso. Por isso disse que não é a melhor das soluções.
Postai pra gente depois que estiver pronto o resultado. Se funcionou ou não.
Postai pra gente depois que estiver pronto o resultado. Se funcionou ou não.
GOSTEI 0
Kapak
18/07/2005
Colegas, aproveitando o gancho, gostaria de saber como vcs fazem no caso de alteração do mesmo registro por dois usuários; ou seja, quando o primeiro altera, o segundo estará alterando dados ´irreais´.
GOSTEI 0
Lynx
18/07/2005
segue abaixo o teste que acabei de fazer e funcionou com a dica de vocês.
procedure TfrmCadEquipamentos.FrameCad1BtnSalvarClick(Sender: TObject);
var
codequipamento : Integer;
begin
if not Verificacao then Exit;
with qryCadEquipamentos do
begin
Close;
SQL.Clear;
if not status then
begin
SQL.Add(´insert into EQUIPAMENTOS ´ +
´(CODEQUIPAMENTO,NOMEQUIPAMENTO,IDCODMOTOR, ´ +
´IDCODCOMPRESSOR,IDCODGAS,VOLTS,VALORUNITARIO)´ +
´values (:CODEQUIPAMENTO,:NOMEQUIPAMENTO, ´ +
´:IDCODMOTOR,:IDCODCOMPRESSOR,:IDCODGAS, ´ +
´:VOLTS,:VALORUNITARIO) ´);
end
else
begin
SQL.Add(´update EQUIPAMENTOS set ´ +
´NOMEQUIPAMENTO = :NOMEQUIPAMENTO, ´ +
´IDCODMOTOR = :IDCODMOTOR, ´ +
´IDCODCOMPRESSOR = :IDCODCOMPRESSOR, ´ +
´IDCODGAS = :IDCODGAS, ´ +
´VOLTS = :VOLTS, ´ +
´VALORUNITARIO = :VALORUNITARIO ´ +
´where CODEQUIPAMENTO =:CODEQUIPAMENTO´);
end;
codequipamento:= StrToInt(edtCodigo.Text);
ParamByName(´NOMEQUIPAMENTO´).AsString:= edtNome.Text;
ParamByName(´IDCODMOTOR´).AsString:= idcodmotor;
ParamByName(´IDCODCOMPRESSOR´).AsString:= idcodcompressor;
ParamByName(´IDCODGAS´).AsString:= idcodgas;
case cmbVolts.ItemIndex of
0:ParamByName(´VOLTS´).AsInteger := 12;
1:ParamByName(´VOLTS´).AsInteger := 24;
end;
vlrunitario:= TextToCurr(edtValor.Text);
ParamByName(´VALORUNITARIO´).AsCurrency:= vlrunitario;
{
Verifica o Código do Equipamento, com a Dica
do Pessoal, que frequenta o fórum (ClubeDelphi).
}
if not status then // Verifica somente, para inserir registro.
begin
qryTesteClubeDelphi.SQL.Clear;
qryTesteClubeDelphi.SQL.Add(´select CODEQUIPAMENTO from EQUIPAMENTOS ´ +
´where CODEQUIPAMENTO = :CODEQUIPAMENTO ´);
qryTesteClubeDelphi.ParamByName(´CODEQUIPAMENTO´).Value:=
codequipamento;
qryTesteClubeDelphi.Open;
if not qryTesteClubeDelphi.IsEmpty then
begin
ShowMessage(´Já Existe um Registro com esse Código. ´ +
´ Seu código foi Alterado para ´+IntToStr(codequipamento +1));
codequipamento:= codequipamento+1;
end;
end;
ParamByName(´CODEQUIPAMENTO´).AsInteger:= codequipamento;
ExecSQL();
end;
GOSTEI 0
Lynx
18/07/2005
kapak agora pegou mesmo...
Somente com tabela de lock acho...
Somente com tabela de lock acho...
GOSTEI 0
Adriano Santos
18/07/2005
kapak,
É eu acredito que somente fazendo uma tabela para controlar isso.
Talvez exista alguma camarada aqui no fórum que tenha um controle mais preciso do que com o uso de lock.
É eu acredito que somente fazendo uma tabela para controlar isso.
Talvez exista alguma camarada aqui no fórum que tenha um controle mais preciso do que com o uso de lock.
GOSTEI 0
Kapak
18/07/2005
Mesmo criando-se uma tabela, como funcionaria ?
Supondo que um terminal acesse o registro 123 e um outro terminal em outra sala tentar acessar o mesmo registro. Fazendo o controle por essa tabela o programa impediria o acesso ? E se o cara esquecer o registro na tela e ir almoçar, ou dar um reset na máquina ? O registro ficaria bloqueado ?
Supondo que um terminal acesse o registro 123 e um outro terminal em outra sala tentar acessar o mesmo registro. Fazendo o controle por essa tabela o programa impediria o acesso ? E se o cara esquecer o registro na tela e ir almoçar, ou dar um reset na máquina ? O registro ficaria bloqueado ?
GOSTEI 0
Lynx
18/07/2005
asrsantos paramos no lock novamente :lol:
se alguém conhece algo melhor no fórum postem aí...
Tenho que sair agora, mais tarde eu volto a observar o tópico.
valeu e obrigado a todos
se alguém conhece algo melhor no fórum postem aí...
Tenho que sair agora, mais tarde eu volto a observar o tópico.
valeu e obrigado a todos
GOSTEI 0
Adriano Santos
18/07/2005
Cada vez que o registro entrar em modo de alteção vc lança o número dele na tabela de lock. Quando o usuário efetuar um post ou cancel no registro ele sai fora da lista de lock.
Quando um usuário tentar entrar no registro e o msm estiver na lista o usuário é avisado e não pode entar como alteração. Eu colocaria como somente leitura.
Mas tem o problema de travamento e o que vc mencionou. Se o usuário for almoçar e esquecer de fechar a tela, o registro ficara bloqueado. Ou msm se a maquina desligar sozinha, travar ou algo do genero.
Quando um usuário tentar entrar no registro e o msm estiver na lista o usuário é avisado e não pode entar como alteração. Eu colocaria como somente leitura.
Mas tem o problema de travamento e o que vc mencionou. Se o usuário for almoçar e esquecer de fechar a tela, o registro ficara bloqueado. Ou msm se a maquina desligar sozinha, travar ou algo do genero.
GOSTEI 0
Adriano Santos
18/07/2005
Então galera, eu sei que tem um jeito bastante eficaz para isso mas é programação no banco de dados. Só que não tenho a mínima idéia de como fazer ou de como funciona. É algo que diz respeito ao isolamento do registro em uma transação, um papo assim.
GOSTEI 0
Kapak
18/07/2005
Atualmente utilizo a seguinte técnica:
Crio um campo numérico na tabela chamado Lock.
O programa de manutenção lê este campo, soma 1 e regrava juntamente com os outros campos modificados.
O lock é feito na hora da atualização do registro por TQuery.ExecSQL com a cláusula Where Lock = Lock lido.
Após o ExecSQL, testo TQuery.RowsAffected e, se retornar 0 dou uma msg dizendo que o registro foi modificado anteriormente, volto a ler e jogo os campos na tela novamente. Gostaria de saber de alguma outra técnica mais prática, pq esta força vc criar um campo adicional na tabela e atualizar por ExecSQL.
Crio um campo numérico na tabela chamado Lock.
O programa de manutenção lê este campo, soma 1 e regrava juntamente com os outros campos modificados.
O lock é feito na hora da atualização do registro por TQuery.ExecSQL com a cláusula Where Lock = Lock lido.
Após o ExecSQL, testo TQuery.RowsAffected e, se retornar 0 dou uma msg dizendo que o registro foi modificado anteriormente, volto a ler e jogo os campos na tela novamente. Gostaria de saber de alguma outra técnica mais prática, pq esta força vc criar um campo adicional na tabela e atualizar por ExecSQL.
GOSTEI 0