Delphi 2010 + Transaction + DataWare
26/02/2013
0
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
Posts
26/02/2013
Francisco Macário
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.
26/02/2013
Antônio Neto
Então usando ClientDataSet não necessitamos de Transações ?
Abraços
26/02/2013
Francisco Macário
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.
26/02/2013
Marco Salles
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/
27/02/2013
Antônio 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
27/02/2013
Marco Salles
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
28/02/2013
Antônio 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
28/02/2013
Antônio 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
28/02/2013
Marco Salles
Generics.Collections na uses
No segundo caso , não entendo o que significa marcar de vermenlho ???
28/02/2013
Francisco Macário
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.
28/02/2013
Antônio 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
28/02/2013
Marco Salles
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
01/03/2013
Antônio Neto
Vou fazer umas conferencias e testar.
Muito obrigado
Neto
30/06/2013
José
Clique aqui para fazer login e interagir na Comunidade :)