AutoIncremento DbExpress Duvidas no botao insert?

Firebird

30/10/2007

Pessoal, boa tarde.

To com uma duvida sobre autroincremento com firebird 2.0 + DBExpress

Por ser um programa multicamadas resolvi fazer assim o autoincremento
Primeiro criei o autoincremento por um SP
CREATE PROCEDURE AUTO_SINDICATO 
RETURNS (
    CODIGO INTEGER)
AS
begin
    codigo = GEN_ID(gen_sindicato_id,1);
    suspend;
  end


Ai no aplicativo tenho o trio de componentes SQLDataSet + DataSetProvider+ClientDataSet e um SQLStoreProc para chamar a SP

E no ClientdataSet no evento onAfterInsert coloquei para disparar a SP
procedure Tdm.cdsSindicatoAfterInsert(DataSet: TDataSet);
begin
  {:Gerando o autoincremento do sindicato}
   SPAutoSindicato.ExecProc;
   cdsSindicato.FieldByName(´ID´).AsInteger:= SPAutoSindicato.Params[0].AsInteger;
end;


Bom nenhum problema ai. O que eu percebi foi no botão de Insert no form, a cada clique no botão insert que eu faço ele incrementa o generators +1, só que se eu apertar no botão cancelar ele nao retorna o autoincremento.

vamos supor que ao cliclar em insert dispara a generatos para o autoincremento 18, ai eu não quero incluir e aperto no botão cancel, e novamente vou querer incluir o lançamento, em vez de pegar o 18 ele gera um novo no caso 19.

O button novo eu fiz assim
procedure TFHerdeiro.btnNovoClick(Sender: TObject);
begin
  {:Muda o autoedit do DataSource para true}
  dsHerdeiro.AutoEdit:=True;
  {:Comandos para inserir um novo associado}
  if not dsHerdeiro.DataSet.Active then
     dsHerdeiro.dataset.open;
     dsHerdeiro.dataset.append;
     {:para que o scrollbox fique sempre no topo ao abrir}
     ScrollBox1.VertScrollBar.Position:=0;
     {:para sempre abrir no tabsheet2 ao incluir algum dados}
     TabSheet2.Show;
end;


e no botão cancel fiz assim
procedure TFHerdeiro.btncancelarClick(Sender: TObject);
begin
  dsHerdeiro.DataSet.Cancel;
  (dsHerdeiro.DataSet as TClientDataSet).CancelUpdates;
end;


Ta faltando algo ai para cancelar ou é assim mesmo?


Obrigado pessoal.
Adriano.


Adriano_servitec

Adriano_servitec

Curtidas 0

Respostas

Gandalf.nho

Gandalf.nho

30/10/2007

É assim mesmo, mesmo cancelando a inserção (rollback) o generator não desfaz o último valor gerado.


GOSTEI 0
Adriano_servitec

Adriano_servitec

30/10/2007

É assim mesmo, mesmo cancelando a inserção (rollback) o generator não desfaz o último valor gerado.
Valeu, obrigado pela resposta.

Adriano.


GOSTEI 0
Sql.pedrojr

Sql.pedrojr

30/10/2007

Se não for uma tabela master de um master/detail, você pode disparar a procedure que busca o autoincremento somente no BEFOREPOST OU BEFOREAPPLYUPDATE, ou seja, somente se o usuário mandar gravar é que voce vai buscar um novo codigo.


GOSTEI 0
Trampo

Trampo

30/10/2007

vc terá que incrementar uma variável id negativamente dec( id) a cada insert.
Na hora de gravar, verifica se o ID é negativo (foi pelo Insert) e aí então incrementa o trigger para substituir o número negativo pelo valor correto.
mande email em pvt que envio o codigo.
Jair


GOSTEI 0
Trampo

Trampo

30/10/2007

é assim:
Na declaração:

private
fNomeID: Integer; /// guarda momentaneamente o ID com numero negativo
~~~~~~~~~~~~~~

no on create do datamodule e no afterApplyUpdate do dataset provider:

fNomeID := 0;


No On New RECORD do client data set) chamado pelo botão insert.

Dec( fNomeID );
cdsCliente.FieldByName(´NomeID´).asInteger := fNomeID;

no before update record do dataset provider:

procedure TDM.dspClientesBeforeUpdateRecord(Sender: TObject;
SourceDS: TDataSet; DeltaDS: TCustomClientDataSet;
UpdateKind: TUpdateKind; var Applied: Boolean);

var Qry:TSQLQuery;
begin
if UpdateKind = ukInsert then // é inserção
begin
Qry := TSQLQuery.Create(nil); {: cria uma instância do objeto}
try
Qry.SQLConnection := DM.SQLConnection1; {: componente de conexão}
if (SourceDS = QryCliente) then // é query PAI
begin
Qry.SQL.Clear;
Qry.SQL.add(´SELECT GEN_ID(SEQ_CADASTRO_NOMEID, 1) AS FNomeID_NOVO FROM rdb$database´);
Qry.Open;
try
fNomeID := Qry.Fieldbyname(´FNOMEID_Novo´).asInteger;
finally // fNOmeID é um campo static externo
Qry.Close;
end; // Atualiza no cds (poPropagateChanges = True)
DeltaDS.FieldbyName(´NomeID´).NewValue := fNomeID ;

end // Se for a tabela Mestre, acaba aqui
else // Selecionar todas tabelas detalhes
begin
{ O Provider já gravou a pai e agora gravará cada uma das filhas }
if (DeltaDS.FieldByName(´NOMEID´).asInteger < 0) then // inserção
DeltaDS.FieldByName(´NomeID´).NewValue := fNomeID; // atualiza todas as qry filhas

if ( SourceDS = QryVacinas ) then // atualiza ID em todas as filhas
begin
// Agora ajustar PK das filhas
if DeltaDS.FieldByName(´VACINAID´).asinteger < 0 then
begin // O valor do ID foi negativo
Qry.Close;
Qry.SQL.Clear;
Qry.SQL.Add(´select GEN_ID(GEN_VACINAS_ID, 1) as FID FROM rdb$database´);
Qry.Open;
try // Calcula o novo numero positivo baseado nos
fVacinaID := Qry.fieldbyname(´FID´).AsInteger;
finally // registros existentes utilizando o Sequence
Qry.Close;
end; // Passa para o cds como o novo valor
DeltaDS.FieldByName(´VACINAID´).NewValue := fVacinaID;
end;

end;
end;
finally
FreeAndNil(Qry);
end;
end; // end ukInsert
end;


O SEQ_CADASTRO_NOMEID deve ter o valor do último registro (NomeID) no arquivo de Cadastro se já contiver dados;

No exemplo uso uma tabela de cadastro e outra de vacinas tomadas pelo cadastrado (inventei esta).
Jair


GOSTEI 0
Adriano_servitec

Adriano_servitec

30/10/2007

Obrigado pela dica pessoal.

Vou adaptar aqui.

Valeu.


GOSTEI 0
POSTAR