Delphi 2010 + Transaction + DataWare
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;
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;
Antônio Neto
Curtidas 0
Respostas
Francisco Macário
26/02/2013
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.
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.
GOSTEI 0
Antônio Neto
26/02/2013
Olá macário, obrigado pelo retorno.
Então usando ClientDataSet não necessitamos de Transações ?
Abraços
Então usando ClientDataSet não necessitamos de Transações ?
Abraços
GOSTEI 0
Francisco Macário
26/02/2013
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.
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.
GOSTEI 0
Marco Salles
26/02/2013
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.
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/
GOSTEI 0
Antônio Neto
26/02/2013
Muito obrigado.
Abraços
Neto
Abraços
Neto
GOSTEI 0
Antônio Neto
26/02/2013
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
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
GOSTEI 0
Marco Salles
26/02/2013
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
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
GOSTEI 0
Antônio Neto
26/02/2013
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
É um senho post estou criando as estruturas e farei passo a passo.
Antecipadamente parabéns pelo post é uma ajuda das grandes.
abraços
Neto
GOSTEI 0
Antônio Neto
26/02/2013
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
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
GOSTEI 0
Marco Salles
26/02/2013
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 ???
Generics.Collections na uses
No segundo caso , não entendo o que significa marcar de vermenlho ???
GOSTEI 0
Francisco Macário
26/02/2013
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 ???
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.
GOSTEI 0
Antônio Neto
26/02/2013
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
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
GOSTEI 0
Marco Salles
26/02/2013
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
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
GOSTEI 0
Antônio Neto
26/02/2013
Ótimo, agora rodou.
Vou fazer umas conferencias e testar.
Muito obrigado
Neto
Vou fazer umas conferencias e testar.
Muito obrigado
Neto
GOSTEI 0
José
26/02/2013
Antonio obrigado por seu retorno. Sendo assim estou dando este tópico por concluído.
GOSTEI 0