Mises à jour en cache (FireDAC)

De Appmethod Topics
Aller à : navigation, rechercher

Remonter à Modification des données (FireDAC)

Informations générales

Le mode Mises à jour en cache permet de différer la validation des mises à jour dans une base de données, au lieu d'appeler les méthodes Post / Delete. Ainsi, il est possible de valider plusieurs mises à jour en un seul traitement par lot, éventuellement intégré dans une transaction.

Pour activer le mode Mises à jour en cache pour un ensemble de données, définissez la propriété CachedUpdates sur True. L'ensemble de données suit alors toutes les modifications apportées depuis la dernière définition de la propriété sur True ou depuis les derniers appels à CancelUpdates / CommitUpdates. Ces modifications sont incluses dans le journal des modifications, qui classe toutes les modifications selon l'heure à laquelle elles ont été effectuées. FireDAC ne fait pas le suivi des diverses versions d'un même enregistrement. La dernière modification remplace les précédentes et place l'enregistrement à la fin de l'ordre de modification.

FireDAC prend en charge les modes Mises à jour en cache décentralisées et centralisées :

  • Mode Mises à jour en cache décentralisées -- chaque ensemble de données effectue le suivi des modifications indépendamment des autres. C'est le mode classique utilisé par défaut.
  • Mode Mises à jour en cache centralisées -- plusieurs ensembles de données partagent un seul et même journal des modifications, dans lequel les modifications sont classées par ordre historique.

Mises à jour centralisées en cache

Lorsque l'application doit se connecter et appliquer plusieurs modifications d'ensembles de données par ordre chronologique, il est possible d'utiliser le mode Mises à jour en cache centralisées. Pour cela, une seule instance de TFDSchemaAdapter doit être assignée à la propriété SchemaAdapter des ensembles de données. TFDSchemaAdapter sert de stockage central des lignes et de leurs modifications dans plusieurs ensembles de données.

Dans un premier temps, le mode Mises à jour en cache centralisées est utile dans les relations maître-détail, où un ensemble de données maître propage les modifications dans les ensembles de données détail en cascade, y compris les valeurs des champs auto-incrémentés. Pour activer la propagation sur un ensemble de données détail, FetchOptions.DetailCascade doit être défini sur True. Cela permet les opérations suivantes :

  • Synchronisation des modifications maître-détail, de sorte que les modifications des ensembles de données maître et détail sont enregistrées et appliquées par ordre chronologique. Par exemple : d'abord l'enregistrement maître inséré, puis les enregistrements détail insérés correspondants.
  • Propagation d'une valeur de colonne identité maître vers un ensemble de données détail. Par exemple, lorsqu'un ensemble de données détail est lié à une colonne identité de l'ensemble de données maître et que vous appliquez des mises à jour, les enregistrements détail correspondants doivent obtenir la valeur réelle de la colonne identité maître.
  • Suppression en cascade des enregistrements détail lors de la suppression d'un enregistrement maître. Par exemple, lorsqu'un enregistrement maître est supprimé, tous les enregistrements détail correspondants sont également supprimés. Cette opération est enregistrée dans le journal des modifications.
  • Propagation en cascade des modifications d'un champ maître vers un ensemble de données détail.

La propagation fonctionne lorsque les conditions suivantes sont satisfaites :

Vous pouvez également utiliser DetailServerCascade pour déterminer si FireDAC répercute les modifications en cascade côté client dans la base de données. DetailServerCascade s'utilise avec FetchOptions.DetailCascade.

Pour activer le mode Mises à jour en cache centralisées avec propagation, effectuez les étapes suivantes (définissez d'abord la relation maître-détail basée sur une plage de valeurs, puis définissez la propriété CachedUpdates sur True) :

  1. Déposez un TFDSchemaAdapter sur une fiche.
  2. Définissez la propriété SchemaAdapter de l'ensemble de données maître sur un TFDSchemaAdapter.
  3. Définissez la propriété SchemaAdapter de l'ensemble de données détail sur un TFDSchemaAdapter.
  4. Définissez la propriété FetchOptions.DetailCascade de l'ensemble de données détail sur True.

Ces étapes activent simultanément une contrainte référentielle en mémoire pour un ensemble de données détail, laquelle est semblable à une commande SQL :

ALTER TABLE <detail> ADD CONSTRAINT
FOREIGN KEY (<detail fields>)
REFERENCES <master> (<master fields>)
ON DELETE CASCADE
ON UPDATE CASCADE

Pour appliquer des mises à jour, l'application doit utiliser la méthode TFDSchemaAdapter.ApplyUpdates au lieu de la méthode ApplyUpdates de l'ensemble de données. Pour concilier les erreurs, utilisez la méthode TFDSchemaAdapter.Reconcile au lieu de la méthode Reconcile de l'ensemble de données.

Pour de plus amples informations, voir l'application exemple FireDAC\Samples\Comp Layer\TFDQuery\CachedUpdates\Centralized.

Suivi des mises à jour

Lorsque votre application fonctionne en mode Mises à jour en cache, vous pouvez suivre les modifications et éventuellement les annuler pour chaque ensemble de données. Pour suivre les modifications, utilisez les propriétés suivantes :

  • UpdatesPending -- renvoie True si le journal des modifications n'est pas vide.
  • ChangeCount -- renvoie le nombre total de modifications.
  • UpdateStatus -- renvoie le type de modification de l'enregistrement en cours.
  • FilterChanges -- autorise le filtrage des enregistrements par type de modification.

Pour annuler les modifications existantes, utilisez les propriétés et méthodes suivantes :

  • SavePoint -- définit/obtient l'état en cours du journal des modifications.
  • RevertRecord -- rétablit l'état antérieur (d'origine) de l'enregistrement en cours.
  • UndoLastChange -- accède au dernier enregistrement modifié et rétablit son état antérieur (d'origine).
  • CancelUpdates -- rétablit tous les enregistrements du journal des modifications.

Par exemple, pour implémenter une fonctionnalité d'annulation (Undo) simple, vous pouvez créer une action actUndo et y attacher les gestionnaires d'événement suivants :

procedure TForm1.actUndoUpdate(Sender: TObject);
begin
  actUndo.Enabled := FDQuery1.UpdatesPending;
end;

procedure TForm1.actUndoExecute(Sender: TObject);
begin
  FDQuery1.UndoLastChange(True);
end;

Comme autre exemple, pour implémenter des transactions en mémoire, avec la possibilité d'annuler un groupe de modifications, vous pouvez procéder comme suit :


FDQuery1.CachedUpdates := True;
iSavePoint := FDQuery1.SavePoint;
try
  FDQuery1.Append;
  ...
  FDQuery1.Post;
  FDQuery1.Append;
  ...
  FDQuery1.Post;
  FDQuery1.Append;
  ...
  FDQuery1.Post;
except
  FDQuery.SavePoint := iSavePoint;
end;

Remarque : En mode Mises à jour en cache, les méthodes et propriétés suivantes fonctionnent avec le journal des mises à jour :

  • La propriété Data inclut tous les enregistrements, même ceux supprimés, et leurs modifications.
  • La propriété Delta renvoie les enregistrements supprimés, insérés ou mis à jour dans le journal des mises à jour.
  • Les méthodes CopyRecord et CopyDataSet créent de nouvelles modifications et ne copient pas le journal des modifications.
  • LoadFromStream, LoadFromFile, SaveToStream et SaveToFile chargent / enregistrent des données avec le journal des mises à jour.

En mode Mises à jour en cache, certains paramètres de méthodes et de propriétés déclenchent une exception, si le journal des mises à jour contient des modifications. Ils doivent être validés ou annulés. Ce sont :

  • Refresh
  • Le fait de définir CachedUpdates sur False.


Application des mises à jour

Pour appliquer des mises à jour à une base de données, utilisez la méthode ApplyUpdates. Si un enregistrement déclenche une exception lors de l'application d'une mise à jour, elle sera associée à l'enregistrement. Notez que la méthode ApplyUpdates :

  • ne déclenche pas une exception, mais renvoie le nombre d'exceptions déclenchées ;
  • n'encapsule pas l'application des mises à jour dans une transaction, une application pouvant elle-même s'en charger ;
  • utilise la même logique de validation des mises à jour que les mises à jour immédiates.

Après l'application des mises à jour, les enregistrements modifiés sont conservés dans le journal des modifications. Pour les retirer du journal des modifications et les marquer comme non modifiés, appelez la méthode CommitUpdates. Par exemple :

FDQuery1.CachedUpdates := True;
FDQuery1.Append;
...
FDQuery1.Post;
FDQuery1.Append;
...
FDQuery1.Post;
FDQuery1.Append;
...
FDQuery1.Post;
FDConnection1.StartTransaction;
iErrors := FDQuery1.ApplyUpdates;
if iErrors = 0 then begin
  FDQuery1.CommitUpdates;
  FDConnection1.Commit;
end
else
  FDConnection1.Rollback;

Remarque : Ce cas correspond au comportement attendu lorsque AutoCommitUpdates est défini sur False.

  • Si vous définissez AutoCommitUpdates sur True, vous n'avez pas besoin d'appeler explicitement CommitUpdates puisque tous les enregistrements actualisés et appliqués par l'appel à ApplyUpdates sont automatiquement marqués comme inchangés.

Examen des erreurs

Si une erreur se produit à l'intérieur de l'appel à ApplyUpdates, ApplyUpdates enregistre l'erreur dans la structure interne des enregistrements de données et continue à traiter les mises à jour jusqu'à ce que le nombre d'erreurs soit égal ou supérieur à AMaxErrors. ApplyUpdates ne déclenche pas d'exceptions. Pour traiter tous les enregistrements erronés après l'appel à ApplyUpdates, utilisez le processus de conciliation ou filtrez les enregistrements erronés.

Pour concilier des enregistrements, assignez le gestionnaire d'événement OnReconcileError et appelez la méthode Reconcile. Le gestionnaire d'événement OnReconcileError permet l'analyse de l'erreur et la lecture / modification des valeurs de champs d'enregistrements en cours. A la fermeture, il doit assigner une action, que le code FireDAC doit récupérer sur l'enregistrement en cours avec l'erreur. Après les appels à la méthode Reconcile, ApplyUpdates peut être à nouveau appelé pour tenter de valider les modifications des enregistrements erronés.

Pour filtrer des enregistrements erronés, incluez rtHasErrors dans FilterChanges. Ensuite, parcourez l'ensemble de données et lisez la propriété RowError pour obtenir un objet exception associé à l'enregistrement en cours. Par exemple :

var
  oErr: EFDException;
...
if FDQuery1.ApplyUpdates > 0 then begin
  FDQuery1.FilterChanges := [rtModified, rtInserted, rtDeleted, rtHasErrors];
  try
    FDQuery1.First;
    while not FDQuery1.Eof do begin
      oErr := FDQuery1.RowError;
      if oErr <> nil then begin
        // process exception object
        ...
      end;
      FDQuery1.Next;
    end;
  finally
    FDQuery1.FilterChanges := [rtUnmodified, rtModified, rtInserted];
  end;
end;

Voir aussi