Ir para conteúdo
Fórum Script Brasil
  • 0

Violação de acesso/ query.create(nil) e query.free


Gabriel Cabral

Pergunta

Galera....não aguento mais esses erros de violação de acesso....

eu nunca sei qual o erro, onde está, o que fazer....

é o seguinte...

num cadastro, faço o incremento de um campo via código...

está assim..

procedure Tdm.tblCadProBeforePost(DataSet: TDataSet);

begin

  if not tblCadPro.FieldByName('PROCOD').IsNull then
    Exit;

    dm.Query1.DatabaseName := tblCadPro.DatabaseName;

    dm.Query1 := dm.Query1.Create(nil);

    try
      dm.Query1.SQL.Add('SELECT MAX (PROCOD) FROM ESTAPRO.dbf');
      dm.Query1.Open;

      try
        tblCadPro.FieldByName('PROCOD').AsString := FloatToStr(StrToFloat(dm.Query1.Fields[0].AsString)+1);
        finally
          dm.Query1.Close;
      end;

      finally
        dm.Query1.Free;
    end;
end;

aí vou testar o programa.....clico em novo, preencho os campos, e gravo...

ok...tudo certo....o programa gera o código desse produto somando um ao max...

mas se vou cadastrar outro logo em seguida, clico em novo, preencho os campos e aí quando clico em gravar, dá o seguinte erro:

Project winsuperm.exe raised exception class EAccessViolation with message 'Access violation at address 00499E41 in module 'winsuperm.exe'. Read of address 0000001C'.

e acusa essas linhas

dm.Query1 := dm.Query1.Create(nil);

e

dm.Query1.Free;

alguém consegue me ajudar ae???

Muito obrigado

Editado por Gabriel Cabral
Link para o comentário
Compartilhar em outros sites

11 respostass a esta questão

Posts Recomendados

  • 0

Galera....não aguento mais esses erros de violação de acesso....

eu nunca sei qual o erro, onde está, o que fazer....

é o seguinte...

num cadastro, faço o incremento de um campo via código...

está assim..

procedure Tdm.tblCadProBeforePost(DataSet: TDataSet);

begin

  if not tblCadPro.FieldByName('PROCOD').IsNull then
    Exit;

    dm.Query1.DatabaseName := tblCadPro.DatabaseName;

    dm.Query1 := dm.Query1.Create(nil);

    try
      dm.Query1.SQL.Add('SELECT MAX (PROCOD) FROM ESTAPRO.dbf');
      dm.Query1.Open;

      try
        tblCadPro.FieldByName('PROCOD').AsString := FloatToStr(StrToFloat(dm.Query1.Fields[0].AsString)+1);
        finally
          dm.Query1.Close;
      end;

      finally
        dm.Query1.Free;
    end;
end;
Tenta mudar essa linha:
[u]dm.Query1 := dm.Query1.Create(nil);[/u]
para
[u]dm.Query1 := dm.Query1.Create(Self);[/u]

Link para o comentário
Compartilhar em outros sites

  • 0
dm.Query1 := dm.Query1.Create(nil);
Gabriel Cabral, tem algo muito errado aqui!

Observo que você está usando:

dm.Query1 := ...

dentro de um procedimento na classe Tdm

Esta é a classe do tal dm que apareceu ali em cima e que é uma variável que provavelmente já está criada (ou você criou o datamodule antes de usá-lo, ou deixou no auto-create de seu projeto)

Logo, se dm já existe, e Query1 faz parte dele (como sugere a mesma linha ali em cima), então você não teria que alocá-lo dinamicamente como aparentemente está tentando fazer. Da mesma forma, não há porque você querer desalocá-lo.

Mas se por acaso este Query1, seja uma variável no na sua unit (e não um componente adicionado ao datamodule), então, você poderia sim fazer a alocação e liberação dinamicamente.

Nesta situação, voce continuaria em erro, pois você deveria utilizar o Create de classe em questão (TQuery) e não o da variável que supostamente ainda não foi inicializada (e ainda que estivesse, continuaria errado)

Ainda outra questão, seria que você só pode atribuir alguma coisa a qualquer propriedade de um objeto, depois que ele está alocado. Logo, não poderia estar acessando a propriedade Database de Query1, se o suposto Create dela seria executado na linha seguinte.

Para a primeira situação (componente Query1 no datamodule), o código teria esta cara:

procedure Tdm.tblCadProBeforePost(DataSet: TDataSet);
begin
  if not tblCadPro.FieldByName('PROCOD').IsNull then
    Exit;
  Query1.DatabaseName := tblCadPro.DatabaseName;
  Query1.SQL.Clear;
  Query1.SQL.Add('SELECT MAX (PROCOD) FROM ESTAPRO.dbf');
  Query1.Open;
  try
    tblCadPro.FieldByName('PROCOD').AsString := FloatToStr(StrToFloat(Query1.Fields[0].AsString)+1);
  finally
    Query1.Close;
  end;
end;
Para a segunda situação (variável Query1 declarada na unit/dm), o código teria esta cara:
procedure Tdm.tblCadProBeforePost(DataSet: TDataSet);
begin
  if not tblCadPro.FieldByName('PROCOD').IsNull then
    Exit;
  Query1 := TQuery.Create(Self);
  Query1.DatabaseName := tblCadPro.DatabaseName;
  try
    Query1.SQL.Add('SELECT MAX (PROCOD) FROM ESTAPRO.dbf');
    Query1.Open;
    try
      tblCadPro.FieldByName('PROCOD').AsString := FloatToStr(StrToFloat(Query1.Fields[0].AsString)+1);
    finally
      Query1.Close;
    end;
  finally
    Query1.Free;
  end;
end;

Abraços

Link para o comentário
Compartilhar em outros sites

  • 0

Entendi Micheus,

no meu caso, tenho um componente Query1 no DataModule...

então coloquei da forma que você indicou...

procedure Tdm.tblCadProBeforePost(DataSet: TDataSet);
begin

  if not tblCadPro.FieldByName('PROCOD').IsNull then
    Exit;

  Query1.DatabaseName := tblCadPro.DatabaseName;
  Query1.SQL.Clear;
  Query1.SQL.Add('SELECT MAX (PROCOD) FROM ESTAPRO.dbf');
  Query1.Open;

  try
    tblCadPro.FieldByName('PROCOD').AsString := FloatToStr(StrToFloat(Query1.Fields[0].AsString)+1);
  finally
    Query1.Close;
  end;

end;

Mas agora ele não está gerando o código.......não está incrementando +1 ao código maximo da tabela

Editado por Gabriel Cabral
Link para o comentário
Compartilhar em outros sites

  • 0

Gabriel Cabral, eu passei batido em uma parte do seu código.

Por acaso PROCOD é um campo varchar na tabela?

Se for numerico, troque:

tblCadPro.FieldByName('PROCOD').AsString := FloatToStr(StrToFloat(Query1.Fields[0].AsString)+1);

por:

tblCadPro.FieldByName('PROCOD').Value := Query1.Fields[0].Value+1;

e veja como fica o resultado

Link para o comentário
Compartilhar em outros sites

  • 0
um grande dum problema....por isso sempre tenho q converter pra float pra somar e depois converter de volta pra str
Gabriel Cabral, isto é bem ruim mesmo e provavelmente você não pode mudar, não é?!

Mas, eu lhe diria que em termos do seu problema inicial, a questão se resolve com o código que você tem agora. Entretanto, passamos a uma nova questão: por que o valor não é incrementado?

Você sabe depurar o código? Se souber adicione um break-point na linha da atribuição do novo valor e quando a execução parar ali, utilizar a caixa de avaliação (CRTL+F7) para verificar o conteúdo do campo.

Se não souber, coloque um ShowMessage antes da atribuição, para que você possa verificar o valor do campo:

...
    ShowMessage(tblCadPro.FieldByName('PROCOD').AsString);
    tblCadPro.FieldByName('PROCOD').AsString := FloatToStr(StrToFloat(Query1.Fields[0].AsString)+1);
...

Abraços

Link para o comentário
Compartilhar em outros sites

  • 0
A execução não está passando por essa procedure...

muito estranho, porque deveria passar independentemente do que há nela, não é?!!

Gabriel Cabral, quando você ápenas compila o código (CTRL+F9), aparecem pequenas bolinhas (pontinhos) azuis na "regua" da margem esqueda do editor de código?

Se não estão aparecendo, é porque este código está sendo ignorado pelo compilador e o provável motivo é que ele não esteja associado ao evento OnBeforePost do dataset tblCadPro - confira!

Se estiver aparecendo, então não haveria motivo para não passar por este evento. Poderia simplesmente estar entrando nele e saindo pelo primeiro if..then onde você chama um Exit. Isto você consegue verificar, também, depurando e pondo um break neste if..then.

Abraços

Link para o comentário
Compartilhar em outros sites

  • 0

Sim, Micheus...os pontinhos azuis estão aparecendo....mas conforme vou dando F7 aqui, não passa por nenhuma linha desse evento....a show message que eu coloquei não aparece em momento nenhum.....

até tirei o if..then pra ver se mudava alguma coisa.....

mas não.....tá o mesmo de sempre....grava o registro mas não gera o código....

seria bom utilizar outro evento pra incrementar o código ou esse mesmo é o ideal???

o código está assim..

procedure Tdm.tblCadProBeforePost(DataSet: TDataSet);
begin

  if not tblCadPro.FieldByName('PROCOD').IsNull then
    Exit;

  Query1.DatabaseName := tblCadPro.DatabaseName;
  Query1.SQL.Clear;
  Query1.SQL.Add('SELECT MAX (PROCOD) FROM ESTAPRO.dbf');
  Query1.Open;

  try
  ShowMessage('teste');
  tblCadPro.FieldByName('PROCOD').AsString := FloatToStr(StrToFloat(Query1.Fields[0].AsString)+1);
  finally
    Query1.Close;
  end;
    
end;

aí o programa passa pelo if...then, não passando pelo Exit

então passa pelas quatro linhas da Query1, e pára na linha Query1.Open;, dando o seguinte erro:

'Query1: Field 'PROCOD' not found'.

e acusa a linha Query1.Close;

Editado por Gabriel Cabral
Link para o comentário
Compartilhar em outros sites

  • 0

Parece que agora consegui resolver esse problema....

espero que tenha conseguido mesmo...

então...eu utilizei outra query pra fazer o incremento no código...

a Query1, que eu estava utilizando para isso, além de utilizar para busca, tinha a propriedade SQL como:

SELECT * FROM ESTAPRO.dbf

a Query2, que estou utilizando agora somente para fazer o incremento, tem a propriedade SQL como:

SELECT PROCOD FROM ESTAPRO.dbf

Link para o comentário
Compartilhar em outros sites

  • 0
então...eu utilizei outra query pra fazer o incremento no código...

a Query1, que eu estava utilizando para isso, além de utilizar para busca, tinha a propriedade SQL como:

SELECT * FROM ESTAPRO.dbf

a Query2, que estou utilizando agora somente para fazer o incremento, tem a propriedade SQL como:

SELECT PROCOD FROM ESTAPRO.dbf

Gabriel Cabral, tomara que tenha mesmo conseguido resolver o problema.

O fato de utilizar o mesmo TQuery para fazer duas coisas distintas, pode mesmo ter sido a causa de seu problema - dependendo de como você estava tratando o uso dela para a consulta. Pela última mensagem de erro que você postou, parece que você teria adicionado os campos ao dataset, o que após substituir a instrução SQL que os adicionou, por outra que não inclua os campos definidos (em Fields), vai sim gerar erro ao abrir esta consulta.

De qualquer modo, nesta sua Query2, você deveria utilizar a mesma consulta que utilizava antes para a obtenção do maior valor - usando MAX.

Abraços

Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,3k
    • Posts
      652,4k
×
×
  • Criar Novo...