Questions relatives à TFDQuery, TFDStoredProc et TFDUpdateSQL

De RAD Studio
Aller à : navigation, rechercher

Remonter à FAQ (FireDAC)

Cette rubrique liste des questions et réponses relatives à TFDQuery, TFDStoredProc et TFDUpdateSQL.

Q1 : Puis-je utiliser TFDQuery et le connecter à un fournisseur d'ensemble de données pour extraire les données dans un ensemble de données client Embarcadero ?

R : TFDQuery combine TFDMemTable, TFDTableAdapter et plusieurs TFDCommand. Par conséquent, TFDQuery comporte déjà tout ce qu'il faut pour exécuter des commandes SQL, envoyer des données de paramètres, recevoir et stocker des ensembles de résultats, parcourir des ensembles de résultats et valider des modifications dans une base de données. Il n'y a aucune raison d'utiliser TFDQuery + DSP + CDS.

Vous pouvez utiliser TFDMemTable, TFDTableAdapter et TFDCommand directement, au lieu de TFDQuery. Ils offrent plus de flexibilité, mais nécessitent également plus de codage. C'est le cas par exemple des mises à jour en cache synchronisées à travers les ensembles de données.

En d'autres termes, TFDQuery est un "raccourci" optimal pour la programmation d'applications de données au quotidien.

Q2 : Comment puis-je forcer FDStoredProc à utiliser des paramètres spécifiés manuellement ?

R : Excluez fiMeta de FetchOptions.Items.

Lorsque vous créez des paramètres manuellement, vous devez exclure fiMeta de FetchOptions.Items. Lorsque cela est spécifié, FireDAC extrait les définitions des paramètres des procédures stockées à partir d'une base de données et renseigne à nouveau la collection Params.

Si vous rencontrez des difficultés avec la définition manuelle des paramètres, renseignez la collection Params automatiquement et vérifiez comment les paramètres sont définis. Ensuite, comparez ce résultat à votre code.

Q3 : '[FireDAC][Phys]-308. Impossible d'ouvrir / définir la commande, qui ne retourne aucun ensemble de résultats' et '[FireDAC][Phys]-310. Impossible d'exécuter la commande retournant un ensemble de résultats'. Qu’est-ce que ces exceptions signifient ?

R : L'exception '[FireDAC][Phys]-308. Impossible d'ouvrir / définir la commande, qui ne retourne aucun ensemble de résultats' est déclenchée lorsque l'application exécute la méthode Open pour une commande SQL qui ne retourne pas d'ensemble de résultats. L'exception est déclenchée après l'exécution de la commande SQL, lorsque le SGBD ne retourne pas d'ensemble de résultats.

L'exception '[FireDAC][Phys]-310. Impossible d'exécuter la commande retournant un ensemble de résultats' est déclenchée lorsque l'application exécute la méthode ExecSQL pour une commande SQL qui retourne un ensemble de résultats. Le fait que la commande retourne un ensemble de résultats ou non est déterminé par le préprocesseur de commande SQL de FireDAC. Si la commande est reconnue en tant que SELECT ou l'une de ses formes, elle retourne un ensemble de résultats ; sinon, elle n'en retourne aucun.

Dans certains cas, FireDAC peut ne pas reconnaître une commande SQL capable de retourner ou non un ensemble de résultats. Parfois, les applications Ad-hoc doivent exécuter une commande SQL, quel que soit le nombre d'ensembles de résultats que cette commande retourne. Que faut-il faire dans ces cas ? Voici deux solutions de base :

1)

 FDQuery1.OpenOrExecute;

Cela peut déclencher en interne une exception [FireDAC][Phys]-308, mais celle-ci ne sera pas propagée en dehors de OpenOrExecute et une commande SQL sera réellement exécutée. Par ailleurs, la méthode retourne True si la commande retourne un ensemble de résultats.

2)

 FDQuery1.Command.CommandKind := skInsert;
 FDQuery1.ExecSQL;

Il vous suffit d'indiquer à FireDAC le type des commandes (INSERT ou autres) qui ne retournent pas d'ensemble de résultats.

Q4 : L'exception 'Mémoire insuffisante' est déclenchée lors de l'appel à FDQuery.Execute(FDQuery.Params.ArraySize). La valeur ArraySize est d'environ 90 000. Qu'est-ce qui ne fonctionne pas ?

R : 1) 90 000 est une valeur trop élevée pour n'importe quel SGBD, car les données sont mises en cache plusieurs fois (paramètres, tampon de l'API du SGBD, tampon du paquet réseau, etc.). Par ailleurs, chaque enregistrement est probablement volumineux. Une application peut également être confrontée aux limitations de l'API du SGBD, telles que la limite supérieure de la taille de tableau. Pour Oracle, cette limite peut aller jusqu'à $7FFF. Pour les autres SGBD, cela dépend de la taille du paquet réseau, etc.

2) Divisez la valeur 90 000 en portions de 500 à 5 000 éléments. Pour cela, voir la démo AD03-ArrayDML. De manière générale, remplissez un tableau jusqu'à atteindre la taille de la portion, puis appelez Execute avec la taille de la portion, remplissez à nouveau, puis appelez Execute, etc.

Avec Firebird, j'utilise ArraySize = 1 000 000 (60 sec) sans problèmes.

Une formule empirique a été trouvée, qui permet de déterminer la taille maximale d'un tableau. FireDAC divise automatiquement un grand tableau en plusieurs portions.

Il n'est pas si simple de trouver une solution similaire pour Oracle. Bien que la limite de taille supportée atteigne $7FFF, les grands tableaux génèrent toujours des violations d'accès et d'autres problèmes.

Quoi qu'il en soit, si la taille d'un enregistrement est trop volumineuse, il se peut que vous soyez à court de mémoire avant même d'avoir appelé la méthode Execute.

Q5 : Est-il possible de savoir si tous les enregistrements FDQuery sont extraits ?

R : Vérifiez la propriété SourceEOF.

Q6 : Je souhaite insérer un enregistrement (via SQL) et obtenir la valeur IDENTITY / SEQUENCE. Quel est le moyen le plus efficace et le plus adapté aux bases de données multiples ?

R : 1) TFDConnection comporte la méthode GetLastAutoGenValue. En fonction du SGBD, il retourne la dernière valeur auto-générée dans une session. Par exemple, pour Oracle, la commande est :

 SELECT <AName>.CURRVAL FROM dual

Pour MySQL, il accède à l'API de MYSQL afin d'obtenir la valeur sans requête SQL. Par ailleurs, si un SGBD ne supporte pas les séquences/générateurs, la valeur du paramètre AName est simplement ignorée.

2) Il n'existe pas de façon commune d'écrire une commande SQL qui insère un enregistrement et retourne une valeur auto-générée. Par exemple, pour Oracle, la commande est :

 INSERT ... INTO ... RETURNING ID INTO :ID

Pour PostgreSQL, il y a deux commandes séparées :

 INSERT ... INTO ..
 SELECT CURRVAL(...)

Lorsque vous validez une insertion dans une base de données en utilisant les méthodes Insert/Post de TDataSet, FireDAC recherche le type de SGBD et génère des commandes SQL efficaces appropriées.

Q7 : Comment puis-je annuler une transaction après que l'utilisateur a annulé l'exécution de la requête en mode amCancelDialog ?

R : Il existe deux options :

1)

 FDTransaction1.StartTransaction;
 try
   FDQuery1.ExecSQL;
   FDTransaction1.Commit;
 except
   on E: EAbort do
     // user canceled the command execution
     ADTransaction1.Rollback;
 end;

2) Créez le gestionnaire d'événement TFDQuery.OnError. Lorsqu'une exécution de commande est annulée, ce gestionnaire d'événement est appelé et le paramètre AException satisfait la condition :

 EFDDBEngineException(AException).Kind = ekCmdAborted;

Q8 : Ma requête contenant les caractères '&', '!' ne s'exécute pas correctement. Quel est le problème ?

R : Par exemple, la commande suivante avec options par défaut ne fonctionne pas :

 FDQuery1.SQL.Text := 'select * from xy where Fieldname = ''xxx&n''';
 FDQuery1.open;

La commande SQL reçue par un SGBD ne voit pas '&n'. En effet, '&' spécifie le début d'une variable de macro. Par défaut, chaque variable a une valeur vide. '&n' est donc remplacé par une chaîne vide. Si vous n'utilisez pas de macros, définissez ResourceOptions.MacroCreate et MacroExpand sur False.

Q9 : J'obtiens l'erreur 'Paramètre Xxx introuvable' lors de l'accès aux paramètres des procédures stockées. Quel est le problème ?

R : Prenez par exemple le code suivant :

 FDStoredProc1.StoredProcName := 'TestProc';
 FDStoredProc1.Prepare;
 FDStoredProc1.ParamByName('Par').AsInteger := 100;

Il peut y avoir différentes raisons à cela :

  • La base de données ne comporte pas la procédure stockée "TestProc" et celle-ci doit donc être créée.
  • En fonction du SGBD, "TestProc" peut être dans un état non valide et doit donc être validé.
  • En fonction du SGBD, le nom de la procédure stockée peut comporter des majuscules et des minuscules et doit être encadré de guillemets.
  • fiMeta est exclu de FetchOptions.Items ; il doit être inclus ou les paramètres doivent être créés manuellement.
  • La procédure stockée ne comporte pas le paramètre Par ; le nom du paramètre doit être corrigé ou le paramètre Par doit être ajouté.
  • En fonction du SGBD, le nom du paramètre peut être préfixé avec '@' ou ResourceOptions.UnifyParams peut être défini sur True.