Newsgroup: it.comp.lang.delphi
Titolo: Problema con AdoQuery

Salve a tutti.
Ho questo problema: utilizzo una adoquery per collegarmi a un db sql server, il codice è più o meno così:
ado_qRighe.SQL.Add('select campo1,');
ado_qRighe.SQL.Add(' campo2,');
ado_qRighe.SQL.Add(' campo3');
ado_qRighe.SQL.Add('from tabella');
ado_qRighe.SQL.Add('where tabella.campo4=''O'' and tabella.campo5='''' ');
poi:
ado_qRighe.Active:=true;
if ado_qRighe.RecordCount<=0 then begin
  ado_qRighe.Active:=false;
  continue;
end else begin
  // leggo ecc...
Tutto bene tranne nel caso in cui ado_qRighe sia vuota, in questo caso non riesco a chiuderla e di conseguenza non riesco a riscriverla al prossimo ciclo (il continue si riferisce a un while). L'errore che mi da è:
'Il record corrente corrisponde all'inizio o alla fine del file oppure è stato eliminato. Per eseguire l'operazione richiesta è necessario disporre di un record corrente'.
Non so come uscirne: per sapere se la query è vuota devo aprirla, se la apro ed è vuota non riesco più a chiuderla pertanto non posso più modificare l'sql per riaprirla. Sto sicuramente sbagliando qualcosa io, ma cosa?
Grazie in anticipo,
Paolo

   continue;
Sarebbe meglio scomodare la proprietà RecordCount il meno possibile.
Puoi ottenere il medesimo risultato testando le proprietà Bof e Eof.
Se invece ti interessa conoscere il numero di record presenti sarebbe 
opportuno eseguire una query "SELECT COUNT(Campo1) FROM TABELLA".
Un saluto
-- 
Emanuele Desideri

   continue;
con
 if ado_qRighe.eof then begin
   ado_qRighe.Active:=false;
   continue;
Stesso errore.
Altri suggerimenti?

 'Il record corrente corrisponde all'inizio o alla fine del file oppure è stato eliminato. Per eseguire l'operazione richiesta è necessario disporre di un record corrente'.
Quell'errore ADO te lo da quando il tuo applicativo usa un riferimento 
ad un record che viene perduto strada facendo, chiudendo la query 
magari. Quel .active := false non va bene e oltretutto non serve: la tua 
query funziona lo stesso senza preventivamente chiuderla.
Abitutati ad usare query.close, e non fa niente se la close chiama 
implicitamente la proprietà active. Close è il metodo che hanno pensato 
proprio per fare quello che dice: aderisci agli standard ogni volta che 
puoi.
Ciao
-- 
morde
D5,D6,D7
Firebird 2.1
QT 4.7.0 (MingW) QT Creator 2.1

 puoi.
Sicuramente c'è qualcosa che mi sfugge ma non capisco, e ho fatto talmente tante prove che sto perdendo la speranza.
Grazie per l'aiuto.

 Sicuramente c'è qualcosa che mi sfugge ma non capisco, e ho fatto talmente tante prove che sto perdendo la speranza.
A questo puntoi se non posti il codice della tua procedura, sarà 
difficile aiutarti ulteriormente.
Facci vedere il codice e vediamo cosa si può fare.
Non è che usi la stessa query una volta per leggere e poi per scrivere?


L'ho depurato delle varie prove. Non fate caso all'SQL (potrei fare un'unica query per vedere il risultato finale ma non posso per vari motivi e non è comunque questo il punto). Nei commenti si vede dove mi da l'errore
Eccolo:
      ado_qOrdini.SQL.Add('select tabella1.campo1,');
      ado_qOrdini.SQL.Add(' tabella1.campo2,');
      ado_qOrdini.SQL.Add(' tabella1.campo3,');
      ado_qOrdini.SQL.Add(' tabella1.campo4');
      ado_qOrdini.SQL.Add('from tabella1');
      ado_qOrdini.SQL.Add('where tabella1.campo5=''O'' and tabella1.campo6='''' and tabella1.campo7<>''S'' ');
      ado_qOrdini.Active:=true;
      ado_qOrdini.First;
      while not(ado_qOrdini.Eof) do begin
        ado_qContaRighe.Active:=false;
        ado_qContaRighe.SQL.Clear;
        ado_qContaRighe.SQL.Add('select count(tabella2.campo1) ');
        ado_qContaRighe.SQL.Add('from tabella2 ');
        ado_qContaRighe.SQL.Add('where tabella2.campo2 =''' + ado_qOrdini.Fields[2].asstring + ''' and ');
        ado_qContaRighe.SQL.Add(' tabella2.campo1 =''' + ado_qOrdini.Fields[0].asstring + ''' and ');
        ado_qContaRighe.SQL.Add(' tabella2.campo3 =''O'' and ');
        ado_qContaRighe.SQL.Add(' tabella2.campo4 ='''' and ');
        ado_qContaRighe.SQL.Add(' tabella2.campo5=''C'' ');
        ado_qContaRighe.Active:=true;
        MessageDlg('HO CONTATO LE RIGHE ' + ado_qContaRighe.Fields[0].AsString, mtInformation, [mbOk], 0);
        if ado_qContaRighe.Fields[0].AsInteger>0 then begin
          MessageDlg('DENTRO LE RIGHE', mtInformation, [mbOk], 0);
          ado_qRighe.SQL.Clear;
          ado_qRighe.SQL.Add('select tabella2.campo1, ');
          ado_qRighe.SQL.Add(' tabella2.campo2, ');
          ado_qRighe.SQL.Add(' tabella2.campo3 ');
          ado_qRighe.SQL.Add('from tabella2 ');
          ado_qRighe.SQL.Add('where tabella2.campo4 =' + ado_qOrdini.Fields[0].asstring + ' and ');
          ado_qRighe.SQL.Add(' tabella2.campo5 =' + ado_qOrdini.Fields[0].asstring + ' and ');
          ado_qRighe.SQL.Add(' tabella2.campo6 =''O'' and ');
          ado_qRighe.SQL.Add(' tabella2.campo7 ='''' and ');
          ado_qRighe.SQL.Add(' tabella2.campo8=''C'' ');
          ado_qRighe.Active:=true;
          MessageDlg('ACTIVE TRUE', mtInformation, [mbOk], 0);
          if ado_qRighe.eof then begin
            MessageDlg('RIGHE EOF', mtInformation, [mbOk], 0);
            ado_qRighe.Active:=false;               // QUI MI DA L'ERRORE, SEMPRE
            MessageDlg('ORDINI NEXT', mtInformation, [mbOk], 0);
            ado_qOrdini.Next;
            continue;
          end else begin
            MessageDlg('CICLO RIGHE', mtInformation, [mbOk], 0);  // QUA NON CI ARRIVA MAI QUINDI POTREBBERO ESSERCI ERRORI
            while not(ado_qRighe.Eof) do begin
              MessageDlg('DENTRO i BARCODE', mtInformation, [mbOk], 0);
 
              ECC... NON CREDO CHE IL RESTO SERVA

 L'ho depurato delle varie prove. Non fate caso all'SQL (potrei fare un'unica query per vedere il risultato finale ma non posso per vari motivi e non è comunque questo il punto). Nei commenti si vede dove mi da l'errore
Ti ho riscritot la funzione in pseudo codice.
Quello che ti chiedo è di fare un refactoring del codice e testare il 
flusso come te l'ho indicato io. Secondo me il next sugli ordini dove 
l'hai messo tu non è corretto.
Cmq, verifica col mio codice se hai ancora i problemi.
E per favore *usa le open e le close* nella posizione dove le ho messe io.
Aspetto feedback
ciao
----------   usa font fixed per visulaizzare indentato bene
       ado_qOrdini.Open;
       ado_qOrdini.First;
       // io considero che .eof diventa true quando fai next dall'ultimo 
record.
       // se apri un recordset con un solo record .eof dovrebbe essere 
false, verifica
       while not(ado_qOrdini.Eof) do begin
           ado_qRighe.Close;
           ado_qRighe.SQL.Add('..................); // impostsa la query
           ado_qRighe.Open;
           ado_qRighe.First;
           while not (ado_qRighe.Eof) do begin
               // elabora barcode o quello che serve..
               //.....
               ado_qRighe.Next;
           end;
           ado_qOrdini.Next;
      end;

In realtà il flusso era questo prima delle mille mila prove che mi hanno portato a stravolgere un pò il tutto, comunque ora lo riscrivo e lo riprovo poi ti faccio sapere.
Ti ringrazio per la disponibilità.
Saluti,
Paolo

Ecco il codice, il primo giro lo fa perfettamente, poi quando si tratta di chiudere qRigheNew (ho provato a rimettere una nuova query pensando magari di aver modificato erroneamente qualche proprietà) va in errore. Se vedi dai commenti ho provato a mettere anche un try except, in questo caso mi da alla riga successiva l'access violation su qRigheNew, senza try mi da il solito 'Il record corrente corrisponde all'inizio o alla fine del file...'
      ado_qOrdini.SQL.Add('.....');
      ado_qOrdini.Open;
      ado_qOrdini.First;
      while not(ado_qOrdini.Eof) do begin
        MessageDlg('CONTO LE RIGHE', mtInformation, [mbOk], 0);
        ado_qContaRighe.Close;
        MessageDlg('PRIMA CHIUDO', mtInformation, [mbOk], 0);
        ado_qContaRighe.SQL.Clear;
        ado_qContaRighe.SQL.Add('...');
        ado_qContaRighe.open;
        MessageDlg('HO CONTATO LE RIGHE ' + ado_qContaRighe.Fields[0].AsString, mtInformation, [mbOk], 0);
        if ado_qContaRighe.Fields[0].AsInteger>0 then begin
          MessageDlg('DENTRO LE RIGHE', mtInformation, [mbOk], 0);
          try
          ado_qRigheNew.Close;   // Senza try dai il solito errore al secondo ciclo, con il try va in except
          except end;
          MessageDlg('CLOSE', mtInformation, [mbOk], 0); 
          ado_qRigheNew.SQL.Clear;  // con il try except da ACCESS VIOLATION
          ado_qRigheNew.SQL.Add('...');
          ado_qRigheNew.open;
          ado_qRigheNew.First;
          MessageDlg('ACTIVE TRUE', mtInformation, [mbOk], 0);
          while not(ado_qRigheNew.Eof) do begin
            MessageDlg('DENTRO i BARCODE', mtInformation, [mbOk], 0);
            ado_qBC.SQL.Clear;
            ado_qBC.SQL.add('select dbo.barcode.bc_code ');
            ado_qBC.SQL.add('from dbo.barcode ');
            ado_qBC.SQL.add('where dbo.barcode.bc_codart = ''' + ado_qRigheNew.Fields[1].AsString + '''');
            ado_qBC.open;
            dsqlInsOrdine.Unprepare;
            dsqlInsOrdine.Prepare;
            dsqlInsOrdine.ParamByName('....
            dsqlInsOrdine.ParamByName('...
            dsqlInsOrdine.ExecSQL;
            ado_qRigheNew.Next;
            ado_qBC.Close;
          end;
          MessageDlg('FUORI CICLO', mtInformation, [mbOk], 0);
        end;
        MessageDlg('CHIUDO 1', mtInformation, [mbOk], 0);
        ado_qContaRighe.Close;
        MessageDlg('NEXT', mtInformation, [mbOk], 0);
        ado_qOrdini.Next;   // NEL PRIMO CICLO FINO A QUI TUTTO BENE, NEL SECONDO SI FERMA SOPRA
      end;

 Ecco il codice, il primo giro lo fa perfettamente, poi quando si tratta di chiudere qRigheNew (ho provato a rimettere una nuova query pensando magari di aver modificato erroneamente qualche proprietà) va in errore.
Sembra tutto ok.. a questo punto puoi provare con l'approccio del 
togliere un pezzo per volta fino a scavare la montagna.
Vale a dire: togli la query sugli ordini, e fagli fare un loop mettendo 
sempre le stesse chiavi nella query righenew, e vedi che succede.
Francamente mi sembra un pò tutto così strano: non ho una gran 
considerazione tecnologica di access ma qui mi sembra che il suo 
utilizzo non sia spinto ai limiti usando concorrenze, page locking, 
transazioni, ecc...
Inoltre, ADO è stato implementato bene nella VCL e quindi, almeno da D7 
in avanti, non mi aspetto strani scherzi di protocollo.
Prova quindi a mantenere la struttura del codice i loop ma usando una 
query per volta e dimmi che succede. Purtroppo io non uso più delphi 7 
altrimenti ti avrei chiesto di mandarmi un programmino di test con il 
tuo db.
ciao


 ciao
mandalo a me, non ti prometto nulla sulla tempistica ma ci do 
volentieri un'occhiata, a questo punto sono curioso!! :-)
buongiorno!
-- 
Emanuele Desideri

 Puoi ottenere il medesimo risultato testando le proprietà Bof e Eof.
Esiste anche IsEmpty.
A.

           MessageDlg('ACTIVE TRUE', mtInformation, [mbOk], 0);
IF (ado_qRighe.ISEMPTY ) then
begin
  log('non ci sono record da processare');
end
else
begin
while true do
begin
  if if ado_qRighe.eof then
  begin
    break;
  end;
  MessageDlg('DENTRO i BARCODE', mtInformation, [mbOk], 0);
  ...
end;
A.

 A.
Ho fatto altre prove, la sostanza è: se la query è vuota o se sono su eof a seguito dei vari next non riesco più a chiuderla (nè col close nè con l'active), mi da l'errore 'Il record corrente corrisponde all'inizio o alla fine del file oppure è stato eliminato. Per eseguire l'operazione richiesta è necessario disporre di un record corrente'. Se la query è popolata fino a che non arrivo a eof tutto funziona correttamente. C'è un motivo plausibile? Vi è mai capitato?

Purtroppo non mi è proprio possibile inviare il db, che poi è sql server.
Oggi non ho avuto molto tempo ma ho fatto altre prove, la sostanza è: se la query è vuota o se sono su eof a seguito dei vari next non riesco più a chiuderla, mi da l'errore 'Il record corrente corrisponde all'inizio o alla fine del file oppure è stato eliminato. Per eseguire l'operazione richiesta è necessario disporre di un record corrente'. Se la query è popolata fino a che non arrivo a eof tutto funziona correttamente. C'è un motivo plausibile? Vi è mai capitato?
Grazie per l'interessamento.

Proverò a ricominciare da capo, ma se non ricordo male tra le tante prove ho fatto anche:
query.open;
query.Close;
e se la query era vuota mi dava direttamente l'errore già detto. Che sia un problema di come mi connetto o dei componenti che uso?


Aggiungo una cosa: se faccio preventivamente il controllo che la query non sia vuota con il count e apro qRighe che abbia sempre almeno un record se la chiudo direttamente (senza leggere record e senza fare next) il ciclo funziona perfettamente. Poi ho provato leggendo il primo record e chiudere senza fare next, tutto ok. Poi ho provato leggendo il primo record e facendo next, e se c'è un solo record sul close mi da l'errore famoso. Ma anche se faccio:
            ado_qRigheNew.Next;
            if ado_qRigheNew.eof then begin
                ado_qRigheNew.Prior;
            end;
            ado_qRigheNew.Close;
Mi fa il prior (nel senso che non mi da errore almeno) ma mi da l'errore sul close.
Non so più che provare. Sostanzialmente quando va in eof la query va in crisi.

 Sostanzialmente quando va in eof la query va in crisi.
Allora verifica:
1- le proprietà della query: cursor, client-server, isolation level, 
ecc... prova a giocare con il keyset.
2- se ado è stato aggiornato all'ultima versione, parti da qui e 
aggiornalo: 
http://msdn.microsoft.com/en-us/data/aa937730
Mal che vada, se non ne esci, per evitare lo scoppio fai un becero 
query.free e la ricostruisci quando serve......
facci sapere,


L'unica cosa che mi viene in mente e' : hai degli eventi gestiti su
questa kaz di adoquery?
A.

 mai capitato?
Se non funziona un motivo plausibile c'è sicuramente.
Mi comincia a venire il dubbio che ci sia qualcos'altro che 
interferisce.
Hai già provato con un semplice programma di test che cicli su una 
query e ad eof la chiuda?
proprio per testarle tutte, provi a lavorare anche su un DB di test, 
con una tabella molto semplice?
Attendiamo notizie :)
-- 
Emanuele Desideri

Aggiornamento: ho portato tutto in un nuovo programma che fa solo e soltanto questo, ho corretto le chiamata a fields[n] con Fields.Fieldbyname('xxx').ecc, ho provato a togliere tutto quello che c'era tra l'open e il next, ma quando arrivo all'eof se chiudo la query mi da sempre il maledetto errore.
Allora ho provato:
qrighe:=TADOQuery.Create(nil);
qrighe.Connection:=....
qrighe.SQL.add ecc
qrighe open
while not qrighe.eof do begin
....
  qrighe.next;
end;
qrighe.Free;
e non ci crederete mai (o almeno io non potevo crederci) il free mi da lo stesso errore del Close!
Prossimo passo: ricrearmi un simil db in locale (non so se lo avevo detto ma quello su cui lavoro è del cliente e non posso manipolarlo molto), ma se anche poi mi funzionasse?
Per quanto riguarda l'aggiornamento dei miei componenti, sono molto ignorante in questo caso, dove vedo quale è la mia attuale versione dell'MDAC ? E poi cercando ho trovato solo la 2.8 per winXP SP2, va bene anche per SP£ ?
Grazie di nuovo a tutti per l'aiuto prezioso e il sostegno morale a questo punto :).

No nessun evento gestito, c'è un aggiornamento situazione in altra risposta se vuoi.
Grazie.



Attenzione fermi tutti: pare risolto, ho compilato su altro pc con delphi probabilmente più aggiornato e pare andare.
Mi cospargo il capo di cenere per avervi tediato finora e non averci provato prima ma ero convinto che il mio delphi fosse a posto. E comunque per me è stato utile lo stesso.
Grazie di nuovo a tutti e alla prossima (speriamo meno tribolata).





 Per quanto riguarda l'aggiornamento dei miei componenti, sono molto ignorante in questo caso, dove vedo quale č la mia attuale versione dell'MDAC ? E poi cercando ho trovato solo la 2.8 per winXP SP2, va bene anche per SPŁ ?
Sulla pagina che ti ho dato c'č se non sbaglio una utility per 
controllare la versione.
Cmq, non sappiamo ancora che versione di delphi stai usando, che 
versione di MDAC hai installato dove hai il problema, che versione di 
sql server.
Inoltre ti avevo chiesto di verificare come imposti la query, dovresti 
aprirla serverside. verifica questo punto č importante, prova un pň.
sto googlando un pň e qeullo che trovo č riconducibile a versioni di 
mdac o di delphi obsolete, risolvibili con update
http://www.delphigroups.info/2/2/601477.htmlad
 esempio...
un'altra domanda che ti voglio fare č:
succede solo con quella tabella specifica? se lo fai su altre tabelle, 
si ripete l'errore?
se crei una tabella clone e fai le query sulla tabella clone, scoppia 
ancora?
L'idea di clonare il db in locale per fare una prova mi sembra ottima.
Quando ci sono questi errori cosě ostinati e inspiegabili, si deve 
provare a cambiare il punto di vista e approcciare il problema da un 
angolo insolito.
Ora io sto guardando l'architettura, lasciando stare il codice.


 Grazie di nuovo a tutti e alla prossima (speriamo meno tribolata).
Ok.
Un'ultima cosa: cerca di capire perchè il tuo google groups, quando 
rispondi, apre ogni volta un nuovo thread aggiungendo Re: R: Re: R: e 
così via.. è molto fastidioso non trovarsi i messaggi tutti organizzati 
sotto il thread di riferimento ;)
Ciao


 sotto il thread di riferimento ;)
Ricorda l'antico bug di OE, quando traduceva il tag Re: con R:... anche
i risultati sono gli stessi...
Per la struttura invece noto che negli header dei messaggi di PT manche
il campo References: che contiene l'id del messaggio al quale si
risponde e permette di mettere in ordine tutta la struttura
indipendentemente dal subject... al suo posto, vedo il campo
In-Reply-To: che dovrebbe funzionare in modo simile... forse il tutto
e` frutto di una qualche *personalizzazione*? come sempre le
personalizzazioni vanno a fare a botte con gli standard... :-)
Ciao ciao
Claudio

 personalizzazioni vanno a fare a botte con gli standard... :-)
Noto solo adesso che piu` banalmente il campo In-Reply-To: e` tipico
dei programmi per le mail, mentre il campo References: e` tipico dei
programmi per le news... quindi facilmente PT posta con un programma
per spedire mail...
Ciao ciao
Claudio

 X-Google-Web-Client: true
Ho messo in crosspost gli amici di it.comp.software.newsreader, forse ci 
potranno aiutare a capirne che newsreader sta usando l'OP :)
Follow-Up su it.comp.software.newsreader.


 Follow-Up su it.comp.software.newsreader.
te lo rimetto in cross, tanto non c'è altro da scoprire.
Ci sarebbe un lungo discorso su come Google si stia comportando peggio 
della Microsoft dei tempi d'oro a proposito di rispetto degli standard, il 
tutto per creare problemi a chi li rispetta. Ma esuliamo dal quesito.
-- 
Sans
Riassunto delle puntate precedenti: 
http://beam.to/mesnews

Sto usando google groups, quello nuovo. Tra l'altro oltre a questo 'piccolo' bug che andrò comunque a verificare mi da problemi nella visualizzazione degli accenti. Ma questo me lo faceva anche con la vecchia versione di google groups.
PS: è comunque ammirevole la vostra abnegazione nella ricerca di risoluzione per qualsiasi tipologia di bug :) Complimenti a tutti!

 il tutto per creare problemi a chi li rispetta. Ma esuliamo dal quesito.
Non sapevo di questo issue: ma proprio google... non si riesce a 
sensibilizzarli su questa cosa? In che modo si può farlo?
Non sia mai che google finisca col monopolizzare anche usenet. Questo 
non lo accetto, visto che sono cresciuto in usenet. ;)
saluti e grazie del supporto


 PS: è comunque ammirevole la vostra abnegazione nella ricerca di risoluzione per qualsiasi tipologia di bug
Deformazione innegabilmente professionale :-D
ciao


 Sto usando google groups, quello nuovo.
Infatti andando a vedere su google gruppi i messaggi risultano tutti
belli ordinati [oltre a segnare correttamente tutti i cambi di
subject]... piuttosto strano, questo incasinamento degli headers [magari
e` un problema solo della nuova versione? speriamo venga anche
corretto] e dei titoli, anche per le curiose abitudini di google
gruppi... :-)
E un ringraziamento da parte mia a morde e Lidrie per le info raggiunte.
Ciao ciao
Claudio

 Non sia mai che google finisca col monopolizzare anche usenet. 
Se google elimina il campo reference, impedisce la corretta
ricostruzione dei thread a chiunque altro.
-- 
 pietro.b
 
http://pib.altervista.org