Bloquear registro firebird com TSimpleDataSet e Delphi 7

Delphi

28/08/2009

Como fazer para bloquear o registro que esta sendo colocado em modo de edição com o componente TSimpleDataSet da dbExpress no Delphi 7 acessando o Firebird 1.5.5.4926... tentei utilizar os comandos WITH LOCK e/ou FOR UPDATE WITH LOCK mas não obtive sucesso.
Por favor me ajudem.


Neodir

Neodir

Curtidas 0

Respostas

Marco Salles

Marco Salles

28/08/2009

Eu acho que o configurando corretamente os Providers Flags dos Tfields
conjutamente com a Opção UpdateMode do TDataSetProvider, vc tera este controle

DataSetProvider >> upWhereAll *******PADRÃO
ProviderFlags dos Tfields > [pfInUpdate,pfInWhere] ******PADRÃO


O Padrão dos Providers Flags ( do DataSetProvider e dos Tfields ) ja tem esta
configuração de Bloqueio ( sem vc mexer sem nada )


Se dois usuários acessarem um Registro , o primeiro que efetiva Alterações
conseguira efetiva no Banco ... O Segundo obtera um erro que sera reportado
no Evento OnReconcileError

.. Talves vc não tenha percebido pq ao dar o ApplayUpdates não é reportado nenhum Erro.. Muito menos ao dar o Post ( ja que os dados estão na
Memória) ..

Mas em contrapartida o Registro Tb Não é Modificado .. Vc acha que foi alterado , mas não foi ( Verifique !!!!)

A pergunta talves seje outra ... Como reportar o Erro para o Usuário que ele
não pode Modificar o Registro naquele Momento , ja que o Registro foi
Modificado primeiro por Outro

Sugestão ...Faça uma pesquisa por Reconncile Error Dialog Aqui mesmo no
site e veja se isto pode te ajudar a informar ao usuário este Bloqueio


GOSTEI 0
Neodir

Neodir

28/08/2009

Cara tem alguma forma de validar via try except sem exibir a tela do EReconcileError?


GOSTEI 0
Marco Salles

Marco Salles

28/08/2009

Não é necessário exibir a tela... Mas vc pode modifica-la , altera-ra , segundo os seu gosto

A exceção é silenciosa , para usar um bloco Try Except vc deve forçar
uma exceção

Por exemplo

try
bla bla
cds.post;
except
//Não captura o erro .. Esta em memória

try
bla bla
cds.ApplayUpdates
except
//captura o erro porém não ira mostrar neste Bloco.. Vai mostrar no Evento
//OnEconcilleErro


try
bla bla
if cds.ApplayUpdates(0) > 0 then // Nenhum erro é tolerável parametro Zero
Raise Cria a Exceção ...
except
//captura o erro criado pela condição


Mas no Post de um registro vc não consegue , a não ser que a cada post
vc force um ApplayUpadtes , que depedendo da situação pode comprometer
a performance de seu aplicativo

Agora vc pode usar o EventoOnEconcileError e Tratar do seu modo a Exceção
lancada , sem ter que chamar o Formulario

Tente isto

procedure TForm1.SeuDataSet1ReconcileError(DataSet: TCustomClientDataSet;
E: EReconcileError; UpdateKind: TUpdateKind; var Action: TReconcileAction);
begin
showmessage(e.Message); //
end;

ps) Ha outra tecnicas tb usando o DataSetProvider


GOSTEI 0
Osocram

Osocram

28/08/2009

Existe algum movito de vc não querer usar o ReconcileError?

Pois o que o Marco Salles comentou esta correto.
E outra... o interessante de se usar o ReconcileError é que os exception do seu DataSet vai estar sempre no mesmo lugar.

Cara tem alguma forma de validar via try except sem exibir a tela do EReconcileError?



GOSTEI 0
Neodir

Neodir

28/08/2009

Não. Não há problema com o EReconcileError é que estou tentando contornar um outro erro que esta acontecendo... a situação é a seguinte:

Transação da operação:
procedure TBase.TransactionBase(myTable: TSimpleDataSet);
var
TD: TTransactionDesc;
begin
if not DmoPrincipal.SQLCBASE.InTransaction then begin
TD.TransactionID := 1;
TD.IsolationLevel := xilREADCOMMITTED;
DmoPrincipal.SQLCBASE.StartTransaction(TD);
try
MyTable.ApplyUpdates(0);
DmoPrincipal.SQLCBASE.Commit(TD);
except
on E :Exception do begin
DmoPrincipal.SQLCBASE.Rollback(TD);
end;
end;
end;
end;

Evento EReconcileError:
if (Pos(´Record not found or changed by another user´, E.Message) > 0) then begin
Application.MessageBox(´Atenção!´+#13+´Não foi possível salvar as Alterações!´,´Sistema´,mb_ok+mb_iconerror);
DataSet.CancelUpdates;
Exit;
end;

após passar pelo evento:
Apresenta uma mensagem de Abstract Error... e se tento colocar um breakpoint para acompanhar passo a passo trava o delphi...


GOSTEI 0
Marco Salles

Marco Salles

28/08/2009

O Porprio midas se encarrega das Transações na tecnologia DbExpress

Vc deve usar Transação explicita , qnd estiver executando Sql
(insert , Update ou Delete) .. Fora isto , não precisa se preocupar que
a Propria instrução ApplayUpdates irá persisitir ou não as Alterações

Mas vc pode testar no seu codigo o seguinte ;

procedure TBase.TransactionBase(myTable: TSimpleDataSet); 
var 
TD: TTransactionDesc; 
begin 
if not DmoPrincipal.SQLCBASE.InTransaction then begin 
TD.TransactionID := 1; 
TD.IsolationLevel := xilREADCOMMITTED; 
DmoPrincipal.SQLCBASE.StartTransaction(TD); 

if MyTable.ApplyUpdates(0) = 0 Then
   DmoPrincipal.SQLCBASE.Commit(TD)
else
DmoPrincipal.SQLCBASE.Rollback(TD); 
end; 




Evento EReconcileError: 
if (Pos(´Record not found or changed by another user´, E.Message) > 0) then begin 
Application.MessageBox(´Atenção!´+#13+´Não foi possível salvar as Alterações!´,´Sistema´,mb_ok+mb_iconerror); 
end; 



GOSTEI 0
Neodir

Neodir

28/08/2009

Valeu pela ajuda pessoal com alguns ajustes no meu código consegui o resultado esperado ao comitar a transação...

[b:a68680d46a]Porém gostaria de saber ainda se há a possibilidade de verificar se o registro está sendo usado por outro usuário no momento de colocá-lo em edição?[/b:a68680d46a]


GOSTEI 0
Marco Salles

Marco Salles

28/08/2009

Não vale a pena vc se preocupar com isto.

É uma questão de Custo Benfecio.. Nesta situação na maior parte das
vezes vence o Custo.

Qauntas vezes durante o Dia terá este conflito e quantas veses não terá

Para verificar isto , mesmo na situação ande não houver conflito , o seu
programa irá custodiar operações na Base De Dados , consumindo Recurso
do Servidor ... Vale a Pena????


GOSTEI 0
POSTAR