2009-05-11 5 views
9

J'ai le code comme ci-dessous dans un projet que je travaille.Combien de temps un signet TDataset reste-t-il valide?

procedure TForm.EditBtnClick(Sender:TObject); 
begin 
    // Mark is form variable. It's private 
    Mark = cdsMain.GetBookmark; 
    // blabalbal 
    . 
    . 
    . 
end; 

procedure TForm.OkBtnClick(Sender:TObject); 
var 
    mistakes: Integer; 
begin 
    //Validation stuff and transaction control 
    //removed to not clutter the code 
    If cdsMain.ChangeCount <> 0 then 
    mistakes := cdsMain.AppyUpdates(-1); 
    cdsMain.Refresh; 
    try 
    cdsMain.GotoBookmark(Mark); 
    // Yes, I know I would have to call FreeBookmark 
    // but I'm just reproducing 
    except 
    cdsMain.First; 
    end; 
end; 

Personnellement, je ne pas utiliser des signets bien - sauf pour repositionner un ensemble de données où je ne déplacé la position du curseur (pour créer une liste, remplir une liste de chaînes, etc.). Si je Refresh, mise à jour (en particulier lorsqu'un filtre peut rendre l'enregistrement invisible), refetch (Close/Open) ou toute opération qui modifie les données dans le jeu de données, je n'utilise pas de signets. Je préfère Locate sur la clé primaire (en utilisant un TClientDataset, bien sûr) ou en modifiant les paramètres.

Jusqu'à quand un signet est-il valide? Jusqu'à un Refresh? Jusqu'à ce qu'un Close/Open soit fait pour reconstituer des données? Où s'arrête la zone de sécurité? Dans la réponse, j'utilise TClientDataset avec un TSQLQuery (DbExpress). TDataSet implémente des méthodes de signet virtuel.

Répondre

5

Comme déjà c0rwin et skamradt déjà mentionné: le comportement du signet dépend du descendant TDataSet que vous utilisez.

En général, les signets deviennent invalides au cours:

  1. fermer/ouvrir
  2. rafraîchissement (sur des ensembles de données qui le supportent)
  3. changements de données (parfois seulement des suppressions)

Je sais 1. et 2. peuvent invalider vos signets dans TClientDataSets. Je suis presque sûr que pour TClientDataSets, le fournisseur sous-jacent n'est pas important (TSQLQuery, TIBQuery, etc.).

La seule façon de vérifier ce qui fonctionne et ce qui ne fonctionne pas est de le tester. Ce qui signifie que vous avez totalement raison de ne pas les utiliser: les signets ont une chance intrinsèque d'être peu fiables. Pour des raisons de sécurité, appelez toujours BookmarkValid avant d'accéder à un signet.

+5

Après quelques expérimentations, même BookmarkValid se montre peu fiable. Cela arrive quand un filtre est activé sur l'ensemble de données - il retourne vrai même si l'enregistrement ne correspond pas à la condition de filtre. Le résultat final est le lancement d'une exception. –

1

Bien que ces méthodes garantissent que tout objet de jeu de données dérivé de TDataSet renvoie une valeur si une méthode de signet est appelée, les valeurs de retour sont simplement des valeurs par défaut qui ne gardent pas trace de l'emplacement actuel. Les descendants de TDataSet, tels que TBDEDataSet, réécrivent les méthodes de signet pour renvoyer des valeurs significatives, comme décrit dans la liste suivante:

  • BookmarkValid, pour déterminer si un signet spécifié est utilisé.
  • CompareBookmarks, pour tester deux signets pour voir s'ils sont identiques.
  • GetBookmark, pour attribuer un signet à votre position actuelle dans l'ensemble de données.
  • GotoBookmark, pour revenir à un signet précédemment créé par GetBookmark
  • FreeBookmark, pour libérer un signet précédemment attribué par GetBookmark.

Recevez de here

+0

Merci. Je vais reformuler la question, donc. –

+0

Malheureusement, je ne me souviens pas de la réponse à cette question, puisque j'ai quitté Delphi il y a longtemps. Mon intuition me dit, elle devrait être valide jusqu'à ce que DataSet soit ouvert, mais je pourrais penser à l'implémentation où elle pourrait être utile même après l'avoir ouverte/fermée. J'ai aussi tendance à être d'accord avec la réponse ci-dessous, car cela pourrait dépendre du fournisseur. –

4

Personnellement, je rarement utiliser les signets. J'utilise à la place l'identifiant de l'enregistrement que je visualise et j'effectue une recherche sur celui-ci une fois que l'actualisation est terminée. Si j'ai besoin d'itérer sur tous les enregistrements de l'ensemble, je le fais en utilisant un clone de tClientDataset (qui obtient son propre curseur).

Je crois comprendre que l'implémentation du signet dépend du fournisseur du descendant tDataset et peut varier entre les implémentations. Dans mon jeu de données très simple (tBinData), j'ai implémenté des signets en tant que numéro d'enregistrement physique afin qu'il persiste entre les rafraîchissements tant que l'enregistrement n'a pas été supprimé. Je ne peux pas dire cela vrai pour toutes les implémentations.

Questions connexes