2011-07-27 4 views
-3

Dans ce cas j'ai du code qui fonctionne sans problème dans un programme existant, mais lance une excecption quand je l'utilise dans un nouveau programme.Quel est le problème avec ce code?

Il ne peut pas être le meilleur code, mais il travaille dans une utilisation quotidienne ...

Function DoSQlCommandWithResultSet(const command : String; 
            AdoConnection : TADOConnection; 
            resultSet : TStringList): Boolean; 
    var i : Integer; 
     AdoQuery : TADOQuery; 
begin 
    Result := True; 
    resultSet.Clear(); 

    AdoQuery := TADOQuery.Create(nil); 
    try 
    AdoQuery.Connection := AdoConnection; 
    AdoQuery.SQL.Add(command); 
    AdoQuery.Open(); 

    i := 0; 
    while not AdoQuery.eof do 
    begin 
     resultSet.Add(ADOQuery.Fields[i].Value); 
     AdoQuery.Next; 
     Inc(i); 
    end; 

    finally 
    AdoQuery.Free(); 
    end; 
end; 

Oui, il a probablement besoin est pas utilisé un try/catch et le résultat booléen, mais fonctionne ...

.... dans le programme précédent, mais dans un nouveau il thows une exception lorsqu'il est appelé ...

procedure TForm1.FormCreate(Sender: TObject); 
    var my_stringlist : TStringList; 
     i : integer; 
begin 
    AdoConnection := TADOConnection.Create(nil); 

    if ConnectToDefaultDatabase(AdoConnection) = False then 
     MessageDlg('Agh !', mtError, [mbOK], 0); 

    my_stringlist := TStringList.Create(); 
    if DoSQlCommandWithResultSet('show databases', AdoConnection, my_stringlist) = False then 
     MessageDlg('Urk !', mtError, [mbOK], 0); 

    for i := 0 to Pred(my_stringlist.Count) do 
     memo1.Lines.Add(my_stringlist.Strings[i]); 
end; // FormCreate() 

maintenant, voici la partie intéressante ... il jette la exception sur Inc(i) et, si je remplace cette boucle while avec une boucle for ...

for i := 0 to Pred(ADOQuery.Fields.count) do 
     resultSet.Add(ADOQuery.Fields[i].Value); 

cela fonctionne très bien.

Je suppose que je pourrais juste utiliser la boucle pour & passer, mais je voudrais comprendre ce qui ne va pas .... quelqu'un peut-il m'expliquer? Merci

+0

hmm, aucun commentaire, aucune réponse et un vote négatif. Je me demande pourquoi il a déprécié. Et me donne envie de suggérer que downvoting ne soit pas autorisé sans une explication. C'est seulement de bons mannequins, et on pourrait s'appuyer sur de telles explications – Mawg

+0

vous avez déjà 2 réponses ... – Yahia

+1

pas au moment où il a été downvoted sans commentaire, je ne l'avais pas. J'adore ce site, mais parfois les downvoters hit & run ... – Mawg

Répondre

6

La première chose qui me saute aux yeux est que

i := 0; 
while not AdoQuery.eof do 
begin 
    resultSet.Add(ADOQuery.Fields[i].Value); 
    AdoQuery.Next; 
    Inc(i); 
end; 

et

for i := 0 to Pred(ADOQuery.Fields.count) do 
    resultSet.Add(ADOQuery.Fields[i].Value); 

sont et non équivalent sémantiquement! Lorsque vous appelez le Next, vous avancez l'enregistrement en cours dans l'ensemble de données. Une boucle jusqu'à ce que vous atteigniez EOF parcourt chaque enregistrement du jeu de données une fois. Mais la deuxième boucle n'appelle jamais Next et ne vérifie pas EOF; c'est saisir tous les champs d'un disque. Si je devais deviner ce qui cause l'exception dans la première boucle, je dirais que vous avez plus d'enregistrements (lignes) que de champs (colonnes) dans votre ensemble de données, et donc après un nombre suffisant d'itérations, i finit à ADOQuery.Fields.Count et vous obtenez un index hors limites erreur.

Qu'est-ce que vous essayez exactement de faire ici?

+0

+1 convenu, ils sont différents. Oups, colonnes/rangs ... vous avez raison, de couse. Cela ressemble au problème. Je vais le recoder, mais pouvez-vous me signaler un code pour l'accès MySql en général? Obius, j'en ai besoin – Mawg

+1

@Mawg: Je ne sais pas trop sur MySQL. Encore une fois, qu'essayez-vous de faire? –

+0

Vous avez trouvé la réponse !! J'ai regardé à travers le vieux code et cette fonction a été seulement appelée avec un quiy qui retournerait une seule colonne d'une seule rangée. Lorsque le nouveau projet a voulu renvoyer des lignes muliptle (une par base de données), vous aviez raison sur i et ADOQuery.Fields.Count Merci encore – Mawg

4

Dans la boucle pendant que vous Looping aussi souvent que il y a sont des documents

while not AdoQuery.eof do 

mais vous accéder au champ

ADOQuery.Fields[i] 

alors que i représente le courant « nombre record » ..

Cela se bloquerait dans n'importe quel programme uniquement en fonction de la relation entre le nombre d'enregistrements de la requête et le nombre de champs de la requête ... dès que s nombre d'enregistrements est plus élevé que le champ compte, il se bloque ...

La boucle fait partie de la solution pour cette ...

mais puisque vous ne fournissez pas les informations si vous avez besoin tous les champs pour un enregistrement ou tous les champs de tous les enregistrements que resultset il est difficile de fournir le code fixe ...

+0

+1 Merci. Je vois l'erreur de mes façons maintenant – Mawg