IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Lazarus Pascal Discussion :

Fermeture d'une base pour écrasement du fichier [Lazarus]


Sujet :

Lazarus Pascal

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2006
    Messages
    29
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2006
    Messages : 29
    Par défaut Fermeture d'une base pour écrasement du fichier
    Bonjour,

    J'utilise un datasource et un Sqlite3Dataset pour travailler avec une petite base sqlite locale.

    J'ai donc une base nommée disons... toto.s3db (c'est une base sqlite3 donc).

    Tout fonctionne à merveille : grilles, suppressions, ajouts et j'en passe.

    Donc c'est génial ... sauf que ...

    J'aimerai que l'utilisateur puisse sauvegarder la base et la récuperer à volonté mais comme je suis un peu spécial je ne veux pas me servir du sql pour générer des scripts de sauvegarde/recuperation de base mais carrément faire du brut de décoffrage : un bon vieux FileCopy.

    Enfin presque car j'utilise un FileCopy spécial donné ici même si je me souviens bien, à savoir celui-ci qui permet déjà de copier le fichier de ma base même ouverte dans un fichier :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    Procedure TForm1.CopyFilePerso(Source: String; Dest: string);
    var
      SourceStream, DestStream: Classes.TFileStream; // source and dest file streams
    Begin
      DestStream := nil;
      // Open source and dest file streams
      SourceStream := Classes.TFileStream.Create(Source, SysUtils.fmOpenRead or SysUtils.fmShareDenyNone);
     // original used SysUtils.fmShareDenyWrite
      try
        DestStream := Classes.TFileStream.Create(Dest, Classes.fmCreate or SysUtils.fmShareExclusive);
        //DestStream := Classes.TFileStream.Create(Dest, Classes.fmCreate or SysUtils.fmShareDenyNone);
        // Copy file from source to dest
        DestStream.CopyFrom(SourceStream, SourceStream.Size);
        // Set dest file's modification date to same as source file
        SysUtils.FileSetDate(DestStream.Handle, SysUtils.FileGetDate(SourceStream.Handle));
      finally
        // Close files
        DestStream.Free;
        SourceStream.Free;
      end;
    End;
    Cela fonctionne parfaitement ainsi pour sauvegarder mon fichier toto.s3db en tout ce qu'on veut.

    Je me retrouve donc avec 10 belle sauvegardes dont le nom est xxxx-SAVE.s3db (oui je sais... 10 sauvegardes, je suis un type prudent limite parano... mais bon... qui peut le plus peut le moins donc l'utilisateur à la possibilité de faire autant de sauvegardes qu'il le désire).

    Jusque là tout va bien... Mais je veux pouvoir aussi récupérer ces sauvegardes. Donc via un système de FileListBox et openDialog classique je récupère mon nom de fichier et je lui demande de faire un :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CopyFilePerso(fichierdepart,fichierarrivee);
    où mon fichierdepart représente le nom du ficheir de sauvegarde et fichierarrivee 'toto.s3db' (Comment ça 'le pauvre il veut écraser la base en cours' ? oO)

    Donc pour pouvoir le faire je ferme ma jolie base toto par ceci :
    (j'ai 2 datasource et Sqlite3Dataset pour travailler sur deux tables différentes)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    DatasourceToto1.Enabled:=false;
    DatasourceToto2.Enabled:=false;
    Sqlite3DatasetToto1.Active:=false;
    Sqlite3DatasetToto2.Active:=false;
    Sqlite3DatasetToto1.FileName:='';
    Sqlite3DatasetToto2.FileName:='';
    Sqlite3DatasetToto1.Close;
    Sqlite3DatasetToto2.Close;
    DatasourceToto1.free;
    DatasourceToto2.free;
    Sqlite3DatasetToto1.free;
    Sqlite3DatasetToto2.free;
    Vous allez me dire 'Mais c'est quoi tous ces active:=false suivis de .close et de .free ?'.

    Le fait est que je ne peux pas écraser ma base ! Alors je tente de fermer la connexion pour libérer le fichier de toutes les façons brouillonnes possible

    Au moment de faire le CopyFilePerso j'ai un beau message d'erreur 'EFCreateError' qui à mon avis signifie que le fichier est toujours utilisé par quelqu'un

    J'ai même tenté un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DeleteFileUTF8(fichierarrivee);
    avant le filecopy mais vous pensez bien que j'ai le même problème.

    Donc deux questions de newb doublé d'un bourrin, tant pis :

    - Existe-t-il une autre façon de fermer la connexion à la base ? (je précise que rien n'est actif non plus sur mes Forms et que le résultat se produit sous IDE ou sous execution avec IDE fermé donc ça ne vient pas de là)

    - Y aurait-il un parametre de la fonction CopyFilePerso à modifier dans le choix des fmxxxxxx ?

    Merci aux bonnes âmes (Philippe ? jamais 2 sans 3 alors... )

    Patrick

  2. #2
    Expert confirmé
    Avatar de Ph. B.
    Homme Profil pro
    Freelance
    Inscrit en
    Avril 2002
    Messages
    1 786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 786
    Par défaut
    Bonjour,
    Citation Envoyé par lepotager Voir le message
    Vous allez me dire 'Mais c'est quoi tous ces active:=false suivis de .close et de .free ?'.
    Tu peux déjà simplifier le code en supprimant les appels à Close car voici ce que fait cette procédure qui n'est pas surchargée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Procedure TDataset.Close;
    begin
      Active:=False;
    end;
    Citation Envoyé par lepotager Voir le message
    Le fait est que je ne peux pas écraser ma base ! Alors je tente de fermer la connexion pour libérer le fichier de toutes les façons brouillonnes possible
    En effet, les fermetures des TSqlite3DataSet ne ferment pas la base, le fichier reste verrouillé avec le résultat que tu constates...
    Citation Envoyé par lepotager Voir le message
    - Existe-t-il une autre façon de fermer la connexion à la base ? (je précise que rien n'est actif non plus sur mes Forms et que le résultat se produit sous IDE ou sous execution avec IDE fermé donc ça ne vient pas de là)
    J'ai bien une bidouille qui peut fonctionner si tu sauvegardes en quittant l'application.
    Après avoir fermé tous tes TSqlite3DataSet (mais pas encore détruit ou en ayant stocké auparavant la propriété SqliteHandle (TPointer) de l'un d'entre eux), tu appelles la procédure sqlite3_close de l'unité sqlite3
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    // Par exemple
    sqlite3_close(Sqlite3Dataset1.SqliteHandle);
    Ensuite tu peux copier ton fichier...
    A la restauration, tu dois faire cela avant la toute 1° ouverture du tout 1° TSqlite3DataSet...
    Citation Envoyé par lepotager Voir le message
    - Y aurait-il un parametre de la fonction CopyFilePerso à modifier dans le choix des fmxxxxxx ?
    Ben non, cf. ci-dessus...
    Citation Envoyé par lepotager Voir le message
    Merci aux bonnes âmes (Philippe ? jamais 2 sans 3 alors... )
    De rien si c'était à moi que tu pensais... ou pas
    --
    Philippe.

  3. #3
    Membre averti
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2006
    Messages
    29
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2006
    Messages : 29
    Par défaut
    Merci Philippe ! (oui je parlais bien de toi )

    Bon je vois que cette de TSqlite3DataSet1 garde le contrôle de mon fichier malgré mes TSqlite3DataSet1.close

    J'ai tenté de faire un TSqlite3DataSet1.close puis un changement de nom de fichier et ré-ouvrir TSqlite3DataSet1 avec ce nouveau nom de fichier mais il s'en balance (j'aime bien tenter des trucs bizarres parfois)

    Et comme je veux pouvoir sauvegarder ma base à tout moment ta solution ne me convient pas (ne frappe pas...)

    Il ne me reste plus qu'à faire une sauvegarde non pas du fichier mais des données.

    Je sais bien que c'est plus logique mais je n'aime pas quand un truc me résiste

    Je laisse ouvert quelques temps au cas ou quelqu'un aurait une mega idée puis le vais mettre en [resolu->arrêter de chercher les complications]

    Encore merci Philippe car sans toi je chercherai encore comment fermer l'accès à mon fichier.

    Patrick

  4. #4
    Expert confirmé
    Avatar de Ph. B.
    Homme Profil pro
    Freelance
    Inscrit en
    Avril 2002
    Messages
    1 786
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2002
    Messages : 1 786
    Par défaut
    Citation Envoyé par lepotager Voir le message
    Bon je vois que cette de TSqlite3DataSet1 garde le contrôle de mon fichier malgré mes TSqlite3DataSet1.close
    C'est l'inconvénient des composants tout intégré...
    Citation Envoyé par lepotager Voir le message
    Je laisse ouvert quelques temps au cas ou quelqu'un aurait une mega idée puis le vais mettre en [resolu->arrêter de chercher les complications]
    Je t'aurais bien conseillé le truc suivant : Remplacer le TSqliteDataSet par l'ensemble TSqliteConnection, TSqlTransaction, TSqlQuery mais j'ai fait un petit test et je m'aperçois que ça ne marche pas pile poil : à la réouverture de la base, ça déclenche l'exception "library routine called out of sequence!"...
    Le bugtracker de Freepascal signale un bug de ce type (n° 16438)qui serait corrigé (si j'ai bien compris dans la version FPC 2.5.1)...
    --
    Philippe.

  5. #5
    Membre émérite
    Homme Profil pro
    Chef de projets retraité
    Inscrit en
    Juillet 2011
    Messages
    452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Chef de projets retraité
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2011
    Messages : 452
    Par défaut
    Bonjour,

    Je crois qu'il peut y avoir un contournement:

    Essaye de renommer le fichier (toto.s3db dans ton exemple).

    Ensuite, tu dois pouvoir copier ta sauvegarde.

    Note bien que tant que l'application n'a pas été fermée/rouverte, tu restes sur l'ancienne base...

  6. #6
    Membre averti
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2006
    Messages
    29
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2006
    Messages : 29
    Par défaut
    Merci à vous deux pour ces précisions.

    Pour philippe : j'avais commencé à développer avec les composants TSqliteConnection, TSqlTransaction, TSqlQuery mais comme j'avais des problèmes de compréhension avec ces outils (le Tsqlquery m'a posé problème avec la façon de s'en servir autrement qu'avec des Select) j'étais passé directement à TSqlite3DataSet que j'ai trouvé plus simple.

    Pour acaumes : hélas je voulais que la recup de la sauvegarde se fasse à tout moment sans quitter l'application et de façon transparente pour l'utilisateur. Et je me dis que si j'arrive a renommer/ecraser le fichier mais que je demande à l'utilisateur de fermer/réouvrir le logiciel, il va bien y avoir un pingouin pour ne pas le faire et continuer à bosser avec la mauvaise base en mémoire qui va ensuite écraser le fichier récupéré au premier ApllyUpdates venu ! (Je viens de tester à l'instant un renameUTF8 mais impossible sur un fichier non libéré ce qui clos la solution).

    Bon et bien il ne me reste qu'à faire un petit système de sauvegarde/récupération de données et non de fichier

    A vouloir faire du brut par fainéantise j'ai juste perdu une journée (qui a dit "bien fait ?" ).

    Encore merci pour votre aide.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 30/07/2008, 18h30
  2. Réponses: 1
    Dernier message: 12/02/2006, 14h58
  3. [FMP]Exporter une base pour Excel2003
    Par Jack55 dans le forum Autres SGBD
    Réponses: 1
    Dernier message: 23/12/2004, 10h59
  4. Détourner une fonction pour copier un fichier en mémoire
    Par Rodrigue dans le forum C++Builder
    Réponses: 6
    Dernier message: 12/11/2003, 08h29

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo