DUVIDAS SOBRE SISTEMA MULTI USUARIO
Não encontrei até hoje nemhum artigo eficiente quanto a isso.
Utilizando .execute"Update tabela", não da certo pois o jet não bloqueia um unico registro e sim a pagina e isso depende do tamanho dos registros.
Selecionando antes o registro e utilizando rs.Update eu consegui, segue exemplo.
Agora Fox, Esse metodo você não é o primeiro que eu vejo aqui recomendando
criar campo booleano e gravar sim quando estiver editando.
Funciona muito bem sem utilizar begintrans, mas utilizando, não funcionou.
e sem controle de transações eu não recomendo.
Se eu estiver errado por favor aguém entre e colabore com o tópico.
Bom, essa foi a forma que consegui.
If MsgBox("Confirma alterar """ & txtRazaoSocial & """", vbQuestion + vbYesNo, "Confirmação de Edição") = vbYes Then
ReplaceTel 'Formata os telefones sem () e -
Me.Enabled = False
Me.MousePointer = 13
Conexao.BeginTrans
RSClientes.Open "Select *From TabClientes Where Codigo=" & lblCodigo & ";", Conexao, adOpenKeyset, adLockOptimistic
On Error Resume Next
lblProcesso = "Sistema em Processamento, aguarde..."
'*******Função que Edita os registros
RSClientes!RazaoSocial = Trim(txtRazaoSocial)
RSClientes!NomeFantasia = Trim(txtNomeFantasia)
RSClientes.Update
If Err Then
Select Case Err.Number
Case -2147217887 'Estão editando o reg ao mesmo tempo
'MsgBox Err.Number & Err.Description
doevents
Err.Clear
Me.MousePointer = 0
Me.Enabled = True
lblProcesso = ""
RSClientes.Close
Set RSClientes = Nothing
Conexao.RollbackTrans
MsgBox "O Registro esta sendo ditado por outro Usuário ao mesmo tempo, Tente Novamente", vbCritical, "Aviso"
Exit Sub
Case Else
DoEvents
Me.MousePointer = 0
Me.Enabled=True
lblProcesso = ""
RSClientes.Close
Set RSClientes = Nothing
Conexao.RollbackTrans
MsgBox "erro", vbCritical, "Aviso"
Exit Sub
End Select
End If
Citação:NIL escreveu:
Agora Fox, Esse metodo você não é o primeiro que eu vejo aqui recomendando
criar campo booleano e gravar sim quando estiver editando.
Funciona muito bem sem utilizar begintrans, mas utilizando, não funcionou.
e sem controle de transações eu não recomendo.
Se eu estiver errado por favor aguém entre e colabore com o tópico.
Nil, pode citar um exemplo com relação ao não funcionamento dos trans no caso em questão ?
' BeginTrans - Dá inicio ao processamento
'CommitTrans - Conclui a transacção
'RollBack - Repõe a situação anterior, ou melhor, não executa a transacção.
[c]Sub begintrans()
bd.BeginTrans
' Aqui abro a tabela, edito, altero enfim, manipulo todos os dados.
If MsgBox("Confirma Alterações ?", vbYesNo) = vbYes Then
[b]bd.CommitTrans' aki confirmo as alterações/edições.
Else
bd.Rollback
End If
End Sub
[/c]
Seguinte: Onde vc coloca o código que altera o campo ex:Editando=True ?
Seguite.
Cada programador utiliza uma lógica pessoal. No meu caso veja bem :
Para o usuário editar um registro é necessario desbloquear o form.
Para desbloquear o form eu verifico se tem alguém editando.
[c]Private Sub cmdAlterar_Click()
On Error GoTo SAIFUNC
cmdGravar.Enabled = False
cmdUltimo.Enabled = False
cmdAnterior.Enabled = False
cmdPrimeiro.Enabled = False
cmdProximo.Enabled = False
cmdSair.Enabled = False
bd.BeginTrans ' atente-se a este momento, onde inicio a transação
Set rsProdutos = New ADODB.Recordset
rsProdutos.Open "select * from produtos WHERE CODBARRAS='" & txt.Item(2).Text & "' order by codproduto", bd, adOpenStatic, adLockOptimistic
LerRegistroAtual ' aki leio o registro atual
Select Case rsProdutos.Fields("AlteradoPor") 'o campo que define se pode ou naum ser editado é o 'mesmo campo que registra quem editou.
Case Is <> 1 ' caso o "alteradopor" for diferente de 1 (ou seja o nome de quem alterou pela ultima vez)
rsProdutos.Fields("AlteradoPor") = 1 ' aki defino que esta sendo editado
rsProdutos.Update ' atualizo o campo
Dim I As Integer
For I = 0 To 20
If txt(I).Locked = True Then: txt(I).Locked = False
If txt(I).Enabled = False Then: txt(I).Enabled = True
Next I
txtUnidade.Enabled = True
Check3.Enabled = True
chkATIVO.Enabled = True
chkPromocional.Enabled = True
cmdSalvar.Enabled = True
cmdAdicionar.Enabled = False
cmdAlterar.Enabled = False
cmdCancelar.Enabled = True
Case Is = 1 ' agora caso o campo seja = a 1
MsgBox "Este registro não poderá ser editado." & vbCrLf & "Tente novamente mais tarde !!!!", vbInformation, "Edição de registro"
cmdExcluir.Enabled = False
cmdSair.Enabled = True
End Select
SAIFUNC:
Select Case Err.Number
Case 0
'faz nada
Case -2147168237
MsgBox "Na última tentativa não foi possÃÂÂvel alterar este registro, " & Chr(10) & "Verifique se já não estão editando!"
bd.RollbackTrans ' aki dou um rollback soh para finalizar a transação, pois se o usuário clicar 'novamente no botão alterar , naum dara o erro
Err.Clear
Case -2147217864
MsgBox Err.Description
End Select
Err.Clear
End Sub
[/c]
Não sei se vc observou , mas em nem um momento vc viu o committrans na rotina acima, ou seja se nada der errado vou para o segundo passo do procediemtno.
Agora a questão esta no botão Salvar, é nele que se o usuário conseguiu desbloquear o form dara inicio nas alterações.
Private Sub cmdSalvar_Click()
On Error GoTo TRATAERRO
cmdUltimo.Enabled = True
cmdAnterior.Enabled = True
cmdPrimeiro.Enabled = True
cmdProximo.Enabled = True
rsProdutos.Fields("Lista") = Check3.Value
rsProdutos.Fields("CODPRODUTO") = txt.Item(2).Text
rsProdutos.Fields("CODBARRAS") = txt.Item(2).Text
rsProdutos.Fields("NOMEPRODUTO") = txt.Item(3).Text
rsProdutos.Fields("PRECOCUSTO") = CCur(txt.Item(4).Text)
BLA
BLA
BLA
BLA
BLA
BLA
BLA
BLA
BLA
rsProdutos.Fields("ALTERADOPOR") = txt.Item(13).Text ' OBSERVE QUE NESTE MOMENTO ESTOU ALTERANDO A CONDIÇÃO 1 DO CAMPO Q DEFINE SE PODE OU NÃO SER ALTERADO.
cmdCancelar.Enabled = False
rsProdutos.Update
bd.CommitTrans ' OLHA A CONFIRAMÇÃO DO BEGINTRANS AKI.....PORTANTO VC NAUM VIU NESTE PROCEDIMENTO A 'CHAMADA PARA O BEGINTRANS, QUE JàFOI FEITA LàNO BOTÃO ALTERAR.
TRATAERRO:
Select Case Err.Number
Case 0
BlockRegistro (I)
cmdAdicionar.Enabled = True
cmdAlterar.Enabled = True
cmdSalvar.Enabled = False
cmdSair.Enabled = True
Case -2147217864
MsgBox "Houve um erro na transação e todas as alterações serão descartadas" & Chr(10) & Err.Description
bd.RollbackTrans
End Select
End Sub
Bem comigo ta funcionando legal, ainda não tive nem um problema
Então é como eu disse acima ,
Citação:. Selecionando o registro asim como voê fez:Utilizando .execute"Update tabela", não da certo pois o jet não bloqueia um unico registro e sim a pagina e isso depende do tamanho dos registros.
Selecionando antes o registro e utilizando rs.Update eu consegui, segue exemplo.
Citação:, e sem utilizar instruçoçes sql "db.Execute Update", eu consegui , mas nem precisou criar campo para isso , o proprio Jet ja se encarregou de bloquear e gerar a mensagem de erro que foi tratada.rsProdutos.Open "select * from produtos WHERE CODBARRAS='" & txt.Item(2).Text & "' order by
O que eu disse é que se você tentar fazer via ".execute, não é possivel."
beleza ?
Citação:NIL escreveu:
Fox,
Então é como eu disse acima , Utilizando .execute Update tabela , não da certo pois o jet não bloqueia um unico registro e sim a pagina e isso depende do tamanho dos registros.
Selecionando antes o registro e utilizando rs.Update eu consegui, segue exemplo. . Selecionando o registro asim como voê fez:
rsProdutos.Open select * from produtos WHERE CODBARRAS=[ÃÂ'] & txt.Item(2).Text & [ÃÂ'] order by , e sem utilizar instruçoçes sql db.Execute Update , eu consegui , mas nem precisou criar campo para isso , o proprio Jet ja se encarregou de bloquear e gerar a mensagem de erro que foi tratada.
O que eu disse é que se você tentar fazer via .execute, não é possivel.
beleza ?
KinGX, o foxman, criou algumas rotinas como ele mesmo comentou cada programador age do jeito q lhe melhor convir, mas concordo com o nil num ponto que se vc estiver usando o DAO, e dois usuarios acessarem a mesma tabela e tentarem alterar o dao irá retornar um erro q vc pode inclusive tratalo muito facilmente ou com mensagens ou simplesmente cancelando a operação, enfim, o dao lhe retorna informações q tu pode ou nao usa-las.
Oq o foxman fez é algo q funciona com certeza, mas eu pergunto o seguinte, é tão necessario toda essa frescura vamos colocar a seguinte situação
cadastro de cliente
nao sei qnto a vcs mas eu geralmente tenho um botao chamado atualizar ou gravar q o recordset esta desconectado para o usuario ele mexe tranquilamente nos campos e se quiser realizar alguma alteração ai sim ele clica no botao "atualizar" ai no momento do click o processo q eu faço
abre recordset
sub de gravação
fecho novamente
cara é milionesimos de segundos, mas funciona e se alguem vier me dizer q sistemas maiores e bla, bla eu discordo pq eu clientes q tem ate 100 maquinas logadas no sistema, e nunca tive problemas claro q em determinadas situações como pedidos, caixas e bla, bla eu uso alguns artificios como trazer registros pelo id do usuario logado, ou pelo ip da mauqina enfim...
Mas sinceramente eu nunca usei committrans ou begin... e olha q o meu sistema é preparado pra trabalhar com firebird, access e mysql, ou seja a interface aceita qualquer um deles, claro dependendo da situação do cliente.
mas ate hoje nao tive necessidade vai ver tb devo ter tido muita sorte pq muitos aqui reclamam de access corrompendo nao sei se é a minha tecnica ou sorte mas tb nunca passei por issso.
Pra finalizar, eu acredito q todas as ideias sao validas algumas com mais processos outras com menos, umas com mais "controles para evitar isso e aquilo e outras com menos" mas no final das contas o interessante é tu aprender com os proprios erros, se é o primeiro sistema multi q tu ta desenvolvendo pode ter certeza q depois dele pronto se vc olhar daqui 6 meses tu vai falar q porcaria vou reescrever tudo denovo e assim vai, ache o seu metodo q lhe de segurança e agilidade pra vc.
é so vc mesmo criar o seu proprio uma maneira bem simples é
pegue o seu projeto compile e ai coloque pra rodar o exe.
ai no seu projeto rode junto e faça os testes como se fosse dois usuarios acessando os mesmo registros vc vera as mensagens de erro que o dao lhe retornará e pode simplesmente trata-las ou fazer como os amigos e criar um simples campo Texto de tamanho 1 ou um booleano (é q o fire nao tem boleano, por isso tenho q me adaptar) e qndo o cara clicar em alterar tu abre o recordset e coloca um A de alterando, e depois q fizer as alterações tu coloca um L de livre e ai é so tu colocar um simples If then antes de executar qualquer coisa pra ler esse campo se tiver A avisa o teu usuario pra esperar e ter paciencia pq tem algum mané alterando o registro e poderá levar horas e as vezes ate meses pra q um usuario consiga digitar algo, heheheheheh geralmente a cada 50 caracteres digitados 40 sao o bakespace
huahuahuahuah
Bem, vamos lá.....
Podem navegar simultaneamente pelos registros, quantos usuários quiserem....portanto, como descrevi no código assim, utilizo dois botões, um alterar (bloqueio apenas o registro em questão) e o salvar.
As firulas ou frescuras (rsrsrsrsrs), no meu caso achei necessária, e de certa forma, naum vi nada além do básico, em um botão ALTERAR e em um botão Salvar, com exceção de 3 linhas de transações dividida entre ambos.
Qual é o seu procedimento utilizado, em caso de dois usuários abrirem o mesmo cadastro no mesmo tempo ? e olha isso acontece.
Como vc trata essa possibilidade ?
A minha forma está resumida em dois botões.