ClientDataSet: como gerenciar acesso concorrente?

Delphi

13/01/2006

quando usamos Query o DataSet tem como saber que um determinado registro está sendo editado e tomar as providências caso um outro usuário tente editar o mesmo.
mas quando usamos o ClientDataSet, como vai ser feito este controle já que ele carrega os dados na memória e fecha a conexão?


Raserafim

Raserafim

Curtidas 0

Respostas

Bruno Belchior

Bruno Belchior

13/01/2006

Não há maneiras (pelo menos diretamente não) para fazer isso, o jeito é implementar o evento [b:2ad98edd77]OnReconcilieError[/b:2ad98edd77] para tomarmos a desição do que e como fazer quando um caso deste acontecer...


GOSTEI 0
Raserafim

Raserafim

13/01/2006

então em uma rede que isso é importante, o ClientDataSet é inviável?
se q não pode ser assim pois este componente é utilizado justamente para aplicações multi-camadas, mas não consegui entender...


GOSTEI 0
Vinicius2k

Vinicius2k

13/01/2006

Colega,

Creio que o que vc deseja fazer chama-se ´Travamento pessimista´. Uma prática muito comum, porém, na maioria das vezes, desnecessária se a questão for analisada com cuidado.
Quando se utiliza bancos de dados Desktop como Paradox, Access, dBase, etc, travar o registro é mais do que uma opção, é uma necessidade, porém, com SGBDs é, quase sempre, desnecessário.

A midas não é capaz de fazer isto. A forma de fazer vai variar de acordo com o SGBD. No Firebird, por exemplo, você precisa executar uma query com a instrução ´FOR UPDATE´ e/ou ´WITH LOCK´:
/* para uma query que retorna múltiplos registros */
select 
  <CAMPOS> 
from 
  <TABELA> 
where 
  <CAMPO> = :parametro 
for update with lock

/* para uma query que retorna apenas um registro */
select 
  <CAMPOS> 
from 
  <TABELA> 
where 
  <CAMPO> = :parametro 
with lock


Nesta execução o(s) registro(s) é/são travado(s) para outros usuários até que a transação que efetou o LOCK seja fechada (commit ou rollback).

Antes de seguir o caminho do travamento pessimista, eu sugiro a leitura deste artigo que, na forma conceitual, é valido para qualquer SGBD, caso o que vc esteja utilizando não seja o FB: http://www.comunidade-firebird.org/cflp/downloads/CFLP_T032.PDF

T+


GOSTEI 0
Raserafim

Raserafim

13/01/2006

humm interessante, vou analisar isto.

então o q aconteceria na seguinte situação:
se eu não me preocupasse com nada disso. e em uma máquina cliente o camarada abrisse o cadastro de clientes em um determinado registro. e em outra máquina abrisse o mesmo cadastro de clientes com o mesmo registro. a primeira máquina alterasse a cidade do cliente, e na segunda alterasse o bairro do cliente. o q aconteceria?


GOSTEI 0
Marcello

Marcello

13/01/2006

Testei a situação q vc sugeriu no meu programa e o q ocorreu foi q o cadastro foi atualizado normalmente, sem erros.
No meu caso coloquei no provider a opção upWhereKeyOnly, então mesmo q altere o mesmo campo do cadastro o q vai valer é o último q foi gravado.
Acho muito díficil a situação de dois usuários atualizarem o cadastro do mesmo cliente, e caso isto ocorra o mais provavel é digitar os mesmos dados - endereço, fone, etc.


GOSTEI 0
Vinicius2k

Vinicius2k

13/01/2006

então o q aconteceria na seguinte situação: se eu não me preocupasse com nada disso. e em uma máquina cliente o camarada abrisse o cadastro de clientes em um determinado registro. e em outra máquina abrisse o mesmo cadastro de clientes com o mesmo registro. a primeira máquina alterasse a cidade do cliente, e na segunda alterasse o bairro do cliente. o q aconteceria?


Depende da configuração do TDataSetProvider. Como o colega Marcello citou com a propriedade ´UpdateMode´ do Provider você pode controlar como ele irá se comportar face a esta situação.

Com ´upWhereAll´ a instrução SQL de UPDATE montada pelo provider irá incluir na cláusula WHERE todos os campos com todos os valores que ele possuia originalmente, consequentemente, só será feita alguma alteração se nenhum dos campos tiverem sido alterados por outro usuário. Com isso a alteração feita pelo primeiro usuário prevalecerá e no evento OnReconcileError do TClientDataSet você terá o erro ´Record changed by another user´, após a tentativa de aplicar as alterações.

Com ´upWhereKeyOnly´ apenas a chave primária é incluída na cláusula WHERE da instrução de UPDATE. Se o primeiro usuário não alterar a chave primária (o que, normalmente, não é permitido por você), as alterações efetuadas pelo segundo usuário serão sobrepostas.

T+


GOSTEI 0
POSTAR