Delphi 2010 + Transaction + DataWare

26/02/2013

1

Olá a todos.

Como faço para usar transações quando utilizo controles DataWare.
Porque se inicio uma inclusão (Insert ou Append) ou uma Alteração (Edit),
isso caracteriza uma transação a ser feita mas o usuário pode iniciar uma operação
desse tipo e deixa-la parada.
Ex. Inicia uma inclusão atende telefone e sai para almoçar sem concluir isso deixa processo aberto sem concluir.
Como se resolve isso ?? Quando usando Edit´s não mexemos com o banco até o momento da gravação mas com
controle DataWare não sei como resolver.
Podem me ajudar? Abaixo parte do código que utilizo mas sem controle de transações.
Abraços

procedure TFrmModelo.Ac_IncluirExecute(Sender: TObject);
begin
PageControl1.ActivePage := TabCadastro;
if not DsBase.DataSet.Active then
dsbase.DataSet.Open
else
dsBase.DataSet.Filtered := false;
Dsbase.DataSet.Insert;
end;

procedure TFrmModelo.Ac_IncluirUpdate(Sender: TObject);
begin
TAction(Sender).Enabled := DsBase.DataSet.State in [DsInactive,dsBrowse];
end;

procedure TFrmModelo.Ac_AlterarExecute(Sender: TObject);
begin
if DsBase.DataSet.Active and not Dsbase.DataSet.IsEmpty then
begin
PageControl1.ActivePage := TabCadastro;
DsBase.DataSet.Edit;
end;
end;

procedure TFrmModelo.Ac_CancelarExecute(Sender: TObject);
begin
TClientDataSet(Dsbase.DataSet).Cancel;
PageControl1.ActivePage := TabConsulta;
end;

procedure TFrmModelo.Ac_ExcluirExecute(Sender: TObject);
begin
if not DsBase.DataSet.IsEmpty then
begin
Dsbase.DataSet.Delete;
if DsBase.DataSet is TClientDataSet then
TClientDataSet(Dsbase.DataSet).ApplyUpdates(0)
end;
end;

procedure TFrmModelo.Ac_GravarExecute(Sender: TObject);
begin
if DsBase.DataSet is TClientDataSet then
begin
TClientDataSet(Dsbase.DataSet).Post;
TClientDataSet(Dsbase.DataSet).ApplyUpdates(0);
end;
PageControl1.ActivePage := TabConsulta;
end;

procedure TFrmModelo.Ac_GravarUpdate(Sender: TObject);
begin
TAction(Sender).Enabled := DsBase.DataSet.State in [DsInsert,dsEdit];
LblDesativaFiltro.Visible := DsBase.DataSet.Filtered;
end;

procedure TFrmModelo.Ac_SairExecute(Sender: TObject);
begin
Close;
end;

procedure TFrmModelo.FormClose(Sender: TObject; var Action: TCloseAction);
begin
DsBase.DataSet.Close;
end;

Responder

Posts

Olá Antonio.

observando seu código, o uso de transação está implícito ao ApplyUpdates. O tempo da transação é minimo.

Como você esta usando ClientDataset, os dados estão em cache. Não há transação aberta com o servidor de dados.

At.
Responder

26/02/2013

Antônio Neto

Olá macário, obrigado pelo retorno.

Então usando ClientDataSet não necessitamos de Transações ?

Abraços
Responder
Olá Antonio.

Para cadastros simples (sem chave estrangeira) acho desnecessário.

Agora por exemplo: A geração de uma nota fiscal, temos o cabeçalho, temos os itens, temos as duplicatas (opcional).
Para este caso é recomendado o uso de transação, pois não podemos ter nota sem itens e itens sem nota. A integridade referencial já trata isso, mas o uso de transação nos da mais controle.

At.
Responder

26/02/2013

Marco Salles

Olá Antonio.

Para cadastros simples (sem chave estrangeira) acho desnecessário.

Agora por exemplo: A geração de uma nota fiscal, temos o cabeçalho, temos os itens, temos as duplicatas (opcional).
Para este caso é recomendado o uso de transação, pois não podemos ter nota sem itens e itens sem nota. A integridade referencial já trata isso, mas o uso de transação nos da mais controle.

At.


O NestedDataSet cuida bem disso .. Tb não é necessário controle transactional para isto porque o ApplyUpdates é feito inclusive no Meste

Porém em DataSnap particularmente prefiro dar o ApplyUpdades no Servidor não no Cliente ..

http://marcosalles.wordpress.com/2011/07/09/applyupdate-aplicacao-de-atualizacoes-para-mais-de-um-clientdataset-em-uma-unica-transacao-com-datasnap/
Responder

26/02/2013

Antônio Neto

Muito obrigado.

Abraços

Neto
Responder

27/02/2013

Antônio Neto

Olá a todos.
Minha preocupação é a seguinte trabalhando com DataWare ao dar um Post o
generator gera a próxima chave primária e se outros usuários estiverem
trabalhando simultaneamente também vão gerar a proxima chave ai
se o eu cancelar o post dado anteriormente vai ficar um vão entre estes
códigos e eu não gostaria que isso acontecesse. Gostaria de gerar a chave no
momento que eu Post + ApplyUpdates.

Neto
Responder

27/02/2013

Marco Salles

Opá ..

Ao dar um Post não é necessário utilizar o gerator para gerar o proximo ID. O Correto é nen fazer isto

O que eu sugiro vc fazer

utilizar um gerador para esseS PK Negativos .. Isto é fácil fazer pode ser com constantes Tipadas (Lembra dela???)

cada post do delph para cad acliente é decrementado o valor do PK

ID :=-1 post
ID :=-2 post
ID :=-3 post
ID :=-4 post
ID :=-5 post .... Não tem problema o outro client da rede ter esse mesmo valores pois estão em mémoria

na hpra de dar o ApplyUpdates vc deve utilizar o evento BeforeUpdateRecord para resolver este valores negativos
e ai sim para cada registro ele faz contato com o Gerator e substitui para esse PK o valor correto

eu fiz algo bem semelhante para Relacionamento DataSnap Mestre Detalhe com NestDataSet

telves se vc tiver um tempinho e quiser estudar a classe acredito que vai servir para o que vc necessita

http://marcosalles.wordpress.com/?s=nesteddataset

[]sds
Responder

28/02/2013

Antônio Neto

Olá marco, obrigado pela sugestão.
É um senho post estou criando as estruturas e farei passo a passo.

Antecipadamente parabéns pelo post é uma ajuda das grandes.

abraços

Neto
Responder

28/02/2013

Antônio Neto

Olá Marco, boa tarde e parabéns pelo exemplo.

Fiz o projeto recomendado no post anterior, me parece muito bacana (fizemos coisa semelhante...).
Mas estou com dois problemas neste exemplo, o primeiro na unidade uGerador_Pk na linha abaixo:

private
FData_Set:TDataSet;
FColecao:TDictionary; >>>>> undeclared identifier "TDictionary"
public
Dataset:TDataSet;

O outro na unidade uServidor_ApplyUpDates nas linhas abaixo:

campo_PK := DeltaDS.FieldByName(F_Applay[SourceDs].FPrimary_Key); >>>>>> FPrimary_Key está grifada vermelho

if (F_Applay[SourceDS].FForeign_Key = EmptyStr) then >>>> FForeign_Key >>> está grifada em vermelho
begin
if (campo_PK.Value < 0) then
begin
Id:= PrimaryKeyValue(SourceDS);
campo_PK.NewValue:= Id;
end;
end
else
begin
campo_FK:=DeltaDS.FieldByName(F_Applay[SourceDs].FForeign_Key); >>>> aqui também (lógico)


Se puder me ajudar será ótimo.

Abraços

Neto
Responder

28/02/2013

Marco Salles

bem para o primeiro caso vc tem que adiconar a unidade

Generics.Collections na uses

No segundo caso , não entendo o que significa marcar de vermenlho ???

Responder
bem para o primeiro caso vc tem que adiconar a unidade

Generics.Collections na uses

No segundo caso , não entendo o que significa marcar de vermenlho ???



Acredito que não esteja reconhecendo as propriedades FPrimary_Key e FForeign_Key

At.
Responder

28/02/2013

Antônio Neto

Olá.
No primeiro caso está declada na uses Generics.Collections na uses, mas esta retornando que não reconhece (o código
está no post eu copiei colei e fiz os ajustes de indentação.
No segundo caso é isso mesmo ele não reconhece as propriedades.

Neto


Responder

28/02/2013

Marco Salles

Opa Neto

Verifiquei que o blog comeu minha classe (geralemente ele faz isto)

a definição correta é assim

FColecao:TDictionary<TDataSet,integer>

para instanciar

constructor TGerador_PK.create;
begin
FColecao:=TDictionary<TDataSet,integer>.Create;
end;

quanto ao

O outro na unidade uServidor_ApplyUpDates nas linhas que fica em vermelho
Aqui tb fica em Vermelho , mas nãi impede a compilação

quanto ao directory vou corrigir no Blog

[]sds
Responder

01/03/2013

Antônio Neto

Ótimo, agora rodou.
Vou fazer umas conferencias e testar.

Muito obrigado

Neto
Responder

30/06/2013

José

Antonio obrigado por seu retorno. Sendo assim estou dando este tópico por concluído.
Responder