Questions relatives aux opérations de modification (FireDAC)

De RAD Studio
Aller à : navigation, rechercher

Remonter à FAQ (FireDAC)

Cette rubrique liste des questions et réponses relatives à la modification des données.

Q1 : Que signifie "[FireDAC][DApt]-400. Commande de mise à jour [0] mise à jour au lieu de l'enregistrement [1]" ?

R : Cette erreur est souvent déclenchée quand FireDAC inclut un champ à virgule flottante / double / unique / date / date/heure / heure ou d'autres champs de table, qui sont soumis à une perte de précision dans la phrase WHERE. Cette perte de précision peut se produire quand une application assigne des valeurs à des paramètres. Résultat : la phrase WHERE ne renvoie aucun enregistrement.

FireDAC peut inclure de tels champs dans WHERE selon la valeur de UpdateOptions.UpdateMode. Vous pouvez parfois voir cette erreur avec upWhereKeyOnly. Même si vous avez spécifié upWhereKeyOnly, FireDAC peut toujours utiliser upWhereAll. Cela se produit quand aucun champ PK n'est défini. Aucun champ PK n'est défini quand :

Autre raison : avec certains SGBD (SQL Server, PostgreSQL), la table comporte un déclencheur qui modifie les données. Avec SQL Server, placez SET NOCOUNT ON au début du déclencheur. Avec PostgreSQL, définissez UpdateOptions.CountUpdatedRecords sur False.

Q2 : Quand est-il nécessaire d'utiliser TFDUpdateSQL ?

R : FireDAC génère automatiquement des commandes SQL de mise à jour quand la commande SQL originale est une commande SELECT simple ou une commande SELECT avec JOIN, auquel cas une table unique préserve les champs de clé primaire. Par conséquent, l'utilisation de TFDUpdateSQL est facultative. TFDUpdateSQL est nécessaire lorsque :

  • La commande SQL originale n'est pas une commande SELECT (par exemple, procédure stockée renvoyant des ensembles de résultats).
  • La commande SQL originale ne préserve pas la clé primaire (par exemple, plusieurs tables jointes, présence de clauses DISTINCT ou GROUP BY).
  • Une application a besoin d'une commande SQL de mise à jour non standard (par exemple, l'application valide les mises à jour à l'aide d'appels de procédures stockées).

Q3 : Est-il possible d'utiliser des macros à l'intérieur d'instructions SQL dans FDUpdateSQL ?

R : Utilisez le code suivant :

 FDUpdateSQL1.Commands[arInsert].MacroByName('MacroName').Value := 'value';

Q4 : En mode CachedUpdates, pourquoi le fait d'appeler ApplyUpdates plusieurs fois tente à nouveau de valider des enregistrements insérés ?

R : Après avoir appelé ApplyUpdate, vous devez appeler CommitUpdates. Après cet appel, toutes les modifications sont supprimées du cache interne.

Q5 : Comment actualiser un TFDQuery détail après le défilement ou la validation d'un TFDQuery maître ?

R : Il existe deux façons de procéder :

  • Implémentez votre propre liaison maître-détail. Pour cela, il vous faut ajouter un gestionnaire d'événement TDataSource.OnDataChange. C'est la méthode "standard".
  • Utilisez des mises à jour en cache centralisées.

Q6 : Comment retirer des enregistrements d'un ensemble de données sans les retirer de la base de données ?

R : Vous pouvez travailler directement avec le stockage interne des données de l'ensemble de données, accessible via la propriété TFDDataSet.Table. Par exemple, pour supprimer la ligne ayant l'index 3, procédez comme suit :

 FDQuery1.Table.Rows[3].Free;
 FDQuery1.UpdateCursorPos;
 FDQuery1.Resync([]);

Par exemple, pour supprimer l'enregistrement en cours, procédez comme suit :

 FDQuery1.UpdateCursorPos;
 FDQuery1.GetRow.Free;
 FDQuery1.UpdateCursorPos;
 FDQuery1.Resync([]);

Enfin, vous pouvez utiliser le mode CachedUpdates. Définissez un ensemble de données en mode Mises à jour en cache, puis supprimez un enregistrement et appelez CommitUpdates.

Q7 : Comment puis-je créer ATable.UpdateToDataset(BTable , 'mykey', [mtufEdit, mtufAppend]) en utilisant FireDAC ?

R : Utilisez la méthode TFDDataSet.CopyDataSet avec les options suivantes :

  • [coAppend] - ajoute tous les enregistrements d'ASource (comme c'était le cas) ;
  • [coEdit] - modifie uniquement les enregistrements avec valeurs clé existantes ;
  • [coAppend, coEdit] - modifie les enregistrements avec clés existantes et ajoute les enregistrements avec clés inexistantes.

Q8 : Comment puis-je affecter une valeur à un champ ftGUID ?

R : Utilisez le code suivant :

 (AMemTable.FieldByName('Field1') as TGUIDField).AsGuid := aGUID;

Q9 : Comment puis-je spécifier une valeur par défaut pour un champ ensemble de données ?

R : Assignez une expression à la propriété TField.DefaultExpression.

Q10 : La propriété TField.DefaultExpression est-elle supportée de la même façon que TField.CustomConstraint, et l'effet de l'expression écrite est-il identique à la valeur par défaut d'un champ ?

Oui, si un champ est un champ ensemble de résultats normal. Si un champ est fkInternalCalc, le résultat de DefaultExpression sera utilisé comme valeur d'un champ et mis à jour comme les autres champs calculés.

Q11 : Une expression {fn DAYOFMONTH({fn CURDATE()})} est-elle correcte ?

R : Non, vous utilisez les fonctions d'échappement FireDAC. Elles sont uniquement supportées dans les commandes SQL, pas dans les expressions. Dans les expressions, comme les contraintes et les expressions de valeur par défaut, vous devez utiliser des fonctions et une syntaxe supportées par l'évaluateur d'expression FireDAC :

 DAYOFMONTH(CURDATE())

Par ailleurs, pour utiliser de telles fonctions, vous devez inclure l'unité uADStanExprFuncs dans votre application.

Q12 : Comment puis-je spécifier la valeur par défaut d'un champ booléen d'un ensemble de données ?

R : Pour spécifier la valeur par défaut d'un champ d'un ensemble de données, assignez l'expression requise à la propriété TField.DefaultExpression.

Pour assigner la valeur par défaut d'un champ booléen, vous pouvez utiliser l'une des chaînes suivantes - F, FA, FAL, FALS, FALSE - comme noms False. Le même principe s'applique pour True.

Q13 : L'affectation de TField.CustomConstraint ne fonctionne pas. Quel est le problème ?

Q : L'ajout de contrainte via :

 FDQuery.FieldByName('FIELD_NAME').CustomConstraint := 'FIELD_NAME > 1';
 FDQuery.UpdateConstraints;
 FDQuery.Table.Constraints.Check(FDQuery.GetRow(), rsModified, ctAtEditEnd);

Ne fonctionne pas et aucune exception n'est déclenchée.

R : C'est normal (explication ci-après).

Q : Mais :

 FDQuery.Constraints.Add.CustomConstraint := 'FIELD_NAME > 1';
 FDQuery.UpdateConstraints;
 FDQuery.Table.Constraints.Check(FDQuery.GetRow(), rsModified, ctAtEditEnd);

Fonctionne ! Pourquoi ?

R : C'est également normal.

Q : Que signifient exactement ctAtEditEnd et ctAtColumnChange ?

R : Ces énumérations spécifient l'événement quand FireDAC doit vérifier les contraintes :

  • ctAtEditEnd - Post est appelée
  • ctAtColumnChange - la valeur d'un champ est modifiée

Maintenant, l'explication :

 FDQuery.FieldByName('FIELD_NAME').CustomConstraint := 'FIELD_NAME > 1';

Cette action ajoute une contrainte au niveau du champ. Ces contraintes sont uniquement vérifiées lors de l'événement ctAtColumnChange.

 FDQuery.Constraints.Add.CustomConstraint := 'FIELD_NAME > 1';

Cette action ajoute une contrainte au niveau de l'enregistrement. Ces contraintes sont uniquement vérifiées lors de l'événement ctAtEditEnd.