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

Bases de données Delphi Discussion :

[XE7][Interbase] Comment gérer soi-même les transactions avec FireDac ?


Sujet :

Bases de données Delphi

  1. #1
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 664
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Haute Savoie (Rhône Alpes)

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

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 664
    Points : 6 967
    Points
    6 967
    Par défaut [XE7][Interbase] Comment gérer soi-même les transactions avec FireDac ?
    J'ai constaté que par défaut le FDConnection est auto-commit (ce que personnellement je trouve dangereux, mais bon ).

    J'ai voulu gérer moi-même les transactions.
    J'ai donc initialisé ces deux propriétés :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    TxOptions.AutoCommit = False
    TxOptions.DisconnectAction = xdRollback
    Mes traitements sont bien encadrés de :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    FDConnection.StartTransaction;
    ...
    FDConnection.Commit;
    avec aux endroits stratégiques les : Et à la fin de l'exécution, rien n'a été enregistré dans la base.

    J'ai tenté d'ajouter un TFDTransaction (avec les mêmes paramètres), mais ça ne change rien.

    En cherchant, je suis tombé sur cette page, mais je n'ai rien vu de nouveau :
    http://docwiki.embarcadero.com/RADSt..._%28FireDAC%29

    Quelle propriété j'aurais raté ?
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. ___ Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.3.2 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.1 Entreprise
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.4)

  2. #2
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 042
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 042
    Points : 40 955
    Points
    40 955
    Billets dans le blog
    62
    Par défaut
    Bonjour,

    je vais peut être dire une bêtise mais il s'agit de l'UpdateTransaction ou de la ReadTransaction (<< propriété transaction)? tu nous indiques pas s'il s'agit de la même
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    566
    Détails du profil
    Informations personnelles :
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2009
    Messages : 566
    Points : 1 045
    Points
    1 045
    Par défaut
    Bonjour,

    Je vais présenter comment je traite la difficulté que vous mentionnée. En fait, la transaction personnalisée est attachée à Query. C'est à partir de ce composant qu'il faut lancer la transaction.

    Le code (extraire d'un exemple actuellement opérationnel) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
      if not Query.Transaction.Active then
        Query.Transaction.StartTransaction;
      try
        .... 
        Query.ExecSQL;
        .... 
        Query.Transaction.Commit;
      except
          ....
          if  Query.Transaction.Active then
            Query.Transaction.Rollback;
          .....
       end;
    L'ensemble de mes transactions est traité ainsi et je n'ai constaté aucune anomalie de fonctionnement.
    Je me souviens qu'au début, j'ai eu quelques difficultés lors de la mise en œuvre car la documentation n' est pas parfaite et notamment pour déterminer si une transaction est encours ou pas.

    Bon courage

  4. #4
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 445
    Points
    28 445
    Par défaut
    moi je suis parti sur une approche plus logique des choses, j'utilise IBDAC mais on doit pouvoir faire la même chose avec tous les composants IB.

    j'ai dérivé TIBCTransaction pour lui ajouter une méthode PrepareSQL

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    function TDynTransaction.PrepareSQL(const SQL: string): TIBCQuery;
    begin
      Result := TIBCQuery.Create(Self);
      Result.Connection := DefaultConnection;
      Result.Transaction := Self;
      Result.SQL.Text := SQL;
    end;
    du coup je travaille comme ceci

    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
     
    var
      Trans: TDynTransaction;
      Query: TIBCQuery;
    begin
      Trans := TDynTransaction.Create(Self);
      Trans.DefaultConnection := Connection;
      Trans.IsolactionLevel := iblReadCommitted;
      Trans.StartTransaction;
      Query := Trans.PrepareSQL('...');
      try
        Query.Params...
        Query.Execute;
        Trans.Commit;
      finally
       Trans.Free;
      end;
    end;
    bon enfin c'est l'idée, car j'ai ajouté une méthode StartTransaction dans un dataModule et que mes query sont recyclés au besoin entre deux PrepareSQL...

    quoi qu'il en soit, c'est la transaction qui crée le Query, et quand elle est détruite, elle détruit tous les TQuery avec elle. Du coup je sais toujours où j'en suis avec l'état de mes transactions.
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  5. #5
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 664
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Haute Savoie (Rhône Alpes)

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

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 664
    Points : 6 967
    Points
    6 967
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    je vais peut être dire une bêtise mais il s'agit de l'UpdateTransaction ou de la ReadTransaction (<< propriété transaction)? tu nous indiques pas s'il s'agit de la même
    J'avais testé la ReadTransaction. Mais suite à ta remarque j'ai testé les deux sans succès.


    Citation Envoyé par seabs Voir le message
    Je vais présenter comment je traite la difficulté que vous mentionnée. En fait, la transaction personnalisée est attachée à Query. C'est à partir de ce composant qu'il faut lancer la transaction.

    Le code (extraire d'un exemple actuellement opérationnel) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
      if not Query.Transaction.Active then
        Query.Transaction.StartTransaction;
      try
        .... 
        Query.ExecSQL;
        .... 
        Query.Transaction.Commit;
      except
          ....
          if  Query.Transaction.Active then
            Query.Transaction.Rollback;
          .....
       end;
    J'ai testé, mais ça ne fonctionne pas mieux (les données ne sont pas enregistrées).
    re-

    Pour l'instant, j'ai du mal à comprendre le fonctionnement : pourquoi est-ce si compliqué ?
    Je me souviens qu'avec le BDE ou les composants ODAC (sous oracle), il suffisait juste de démarrer la transaction (avec le TDatabase ou le TConnection) et de commiter à la fin avec le même composant. Et entre les deux, je pouvais utiliser autant que TQuery que je voulais pour faire tous les traitements utiles.

    Citation Envoyé par Paul TOTH Voir le message
    j'ai dérivé TIBCTransaction pour lui ajouter une méthode PrepareSQL
    J'aimerais bien éviter d'en arriver là.
    Je me dis que de base, ces composants doivent savoir gérer une transaction sans avoir besoin de créer de nouveaux composants.
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. ___ Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.3.2 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.1 Entreprise
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.4)

  6. #6
    Membre expert
    Avatar de Barbibulle
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    2 048
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 2 048
    Points : 3 342
    Points
    3 342
    Par défaut
    Les composants pour mettre à jour utilisent bien ceux de la connexion ?

    Car si tu a mis des composants de transaction attaché à tes composants de mise à jour ce n'est pas avec ton FDConnection.StartTransaction; que tu vas y arriver.

    Et tes transactions ne seraient pas des snapshot ??? Comment les as tu paramétrées ?

  7. #7
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 664
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Haute Savoie (Rhône Alpes)

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

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 664
    Points : 6 967
    Points
    6 967
    Par défaut
    Voici mes composants :

    FDConnection :
    DriverName = IB
    LoginPrompt = False
    Params.Database = la base
    Params.DriverID = IB
    Params.Password = le mdp
    Params.Port = 3050
    Params.Protocol = ipLocal
    Params.UserName = le login
    TxOptions.AutoCommit = False
    TxOptions.DisconnectAction = xdRollback
    Transaction = FDTransaction
    UpdateTransaction = FDTransaction

    FDGUIxWaitCursor

    FDPhysIBDriverLink

    FDTransaction :
    Connection = FDConnection
    Options.AutoCommit = False
    Options.DisconnectAction = xdRollback

    Et pour les diverses FDQuery :
    Connection = FDConnection
    Transaction = FDTransaction
    UpdateTransaction = FDTransaction

    Suite aux conseils de seabs, voici mon code modifié :
    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
    FDQuery.Transaction.StartTransaction;
    ...
    FDQuery.Close;
    FDQuery.SQL.Clear;
    FDQuery.SQL.Add('...');
    try
    ...
    	FDQuery.Open;
    except
    ...
    	FDQuery.Transaction.Rollback;
    ...
    end;
    ...      // et ainsi de suite jusqu'au commit.
    FDQuery.Transaction.Commit;
    Auparavant, je n'utilisais pas le FDTransaction (je ne savais même pas qu'il existait), et je faisais directement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    FDConnection.StartTransaction ...
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. ___ Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.3.2 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.1 Entreprise
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.4)

  8. #8
    Membre expert
    Avatar de Barbibulle
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    2 048
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 2 048
    Points : 3 342
    Points
    3 342
    Par défaut
    Oui c'est mieux d'utiliser la transaction à partir du Query que tu utilises même si dans ton cas c'est la même que celle de FDConnection.

    Par contre je ne connais pas bien firedac, mais en regardant dans les options je vois :

    • Options.AutoStart
    • Options.AutoStop
    • Options.EnabledNested


    Si tu veux gérer toi même explicitement tes transaction je placerai ces options à false.

    Et a mon avis c'est Options.EnabledNested la source de tes problèmes.
    Car si je comprend bien cette option c'est pour gérer automatiquement des transactions imbriquées.
    Donc a mon avis tu fais effectivement les commits de tes query mais dans des "sous-transactions" et tu ne commit pas la transaction mère. Comme tu as mis Options.DisconnectAction = xdRollback lors de la fermeture, tout est annulé....

    Ces options ne sont pas trop documentés, ça vaudrait le coup de faire un petit logiciel de test pour voir le comportement de tout ça.

  9. #9
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 664
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Haute Savoie (Rhône Alpes)

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

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 664
    Points : 6 967
    Points
    6 967
    Par défaut
    Citation Envoyé par Barbibulle Voir le message
    Par contre je ne connais pas bien firedac, mais en regardant dans les options je vois :
    • Options.AutoStart
    • Options.AutoStop
    • Options.EnabledNested

    Si tu veux gérer toi même explicitement tes transaction je placerai ces options à false.
    J'ai initialisé :
    FDConnection.TxOptions.AutoStart = False
    FDConnection.TxOptions.EnabledNested = False
    FDTransaction.Options.AutoStart = False
    FDTransaction.Options.EnabledNested = False
    Pour AutoStop, c'était déjà à False.

    Et j'obtiens l'erreur suivante :
    Le projet TraitementSegef.exe a déclenché la classe d'exception EIBNativeException avec le message '[FireDAC][Phys][IB]Dynamic SQL Error
    SQL error code = -204
    Table unknown
    Si je réactive AutoStart :
    Le projet TraitementSegef.exe a déclenché la classe d'exception EFDException avec le message '[FireDAC][Phys][IB]-318. La transaction [TFDPhysIBTransactionBase] doit être inactive. Les transactions imbriquées sont désactivées'.


    Citation Envoyé par Barbibulle Voir le message
    Et a mon avis c'est Options.EnabledNested la source de tes problèmes.
    Car si je comprend bien cette option c'est pour gérer automatiquement des transactions imbriquées.
    Donc a mon avis tu fais effectivement les commits de tes query mais dans des "sous-transactions" et tu ne commit pas la transaction mère. Comme tu as mis Options.DisconnectAction = xdRollback lors de la fermeture, tout est annulé....
    Je vois ce que tu veux dire. Mais, ça n'a pas l'air d'être aussi simple.

    Citation Envoyé par Barbibulle Voir le message
    Ces options ne sont pas trop documentés, ça vaudrait le coup de faire un petit logiciel de test pour voir le comportement de tout ça.
    Pour l'instant, je suis passé sur un autre projet. Donc, je ne peux plus y consacrer le temps que je voudrais.
    Mais, il va falloir que je trouve ...
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. ___ Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.3.2 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.1 Entreprise
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.4)

  10. #10
    Membre expert
    Avatar de Barbibulle
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    2 048
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 2 048
    Points : 3 342
    Points
    3 342
    Par défaut
    Avec les paramètres tels que je les ai donné, il faut explicitement démarrer et terminer les transactions.

    Les messages que tu as prouves qu'il y a des requêtes qui sont exécutés alors que tu n'as pas démarré explicitement de transaction. ça corrobore ma théorie avec le EnabledNested et AutoStart qui étaient à true. Une transaction est ouverte de manière automatique (car une requête est faite sans que tu ne fasses de startTransaction) les startTransactions que tu as pu faire s'effectuaient dans la transaction principale comme des sous-transaction. Et finalement à la fin de ton programme comme tu ne fermes pas explicitement cette transaction principale et que tu as mis DisconnectAction = xdRollback, tout est annulé.

    Le mieux pour débuter c'est de faire ce qui est préconisé : (dans le lien que tu as donné au début dans le paragraphe "Transactions actives multiples")

    Deux transactions une en readonly pour la readtransaction et l'autre readonly=false pour la update transaction.

    Quelle avantage ?
    Performance et plus facile à gérer.
    Interbase/firebird utilisent une transaction pour un simple select. Si tu utilises qu'une seule transaction pour le select et l'update ca sera une transaction longue (qui est donc plus lourde à gérer pour le SG
    Cette transaction ne se libérera pas tant que ton select sera actif. Si tu veux commiter tes update il te faut faire Commitretaining car le commit ça fermer la transaction et donc fermer ton select...
    En utilisant une transaction longue en readonly la charge est plus légère pour le SGBD. Une transaction dédiés aux mises à jours permettra d'avoir des transactions courtes, juste le temps de l'update.
    Ce paramétrage va couvrir les cas les plus classiques (et donc les plus nombreux) des besoins.
    Ce que je décris c'est en utilisant IBX sous Delphi7, il est possible que Firedac gère différemment la transaction de lecture en la fermant automatiquement après avoir mémorisé le résultat du select. Dans tous les cas cette transaction readonly sera sera moins lourde qu'une transaction fourre-tout.

    Parfois faut pouvoir faire plusieurs updates avant de commit/rollback.
    Pour ce faire il suffira de ne pas utiliser les transactions par défauts et en créées une nouvelle (nouveau composant qu'on aura configuré en autostop := false et AutoCommit = False).
    Cette transaction étant relié aux composants qui vont gérés le traitement.
    Traitement qui démarrera (ou non puisqu'on à laissé et Autostart à true) par un StartTransaction
    et devra se terminer par un commit/rollback (si on a laissé EnabledNested := true) il faut s'assurer qu'on a bien commit/rollback la transaction principale... (le mieux à mon avis avec l'option EnabledNested := true c'est de mettre autostart := false ainsi on doit avoir autant de start que de commit/rollback dans le code).

  11. #11
    Expert éminent
    Avatar de Lung
    Profil pro
    Analyste-programmeur
    Inscrit en
    Mai 2002
    Messages
    2 664
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Haute Savoie (Rhône Alpes)

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

    Informations forums :
    Inscription : Mai 2002
    Messages : 2 664
    Points : 6 967
    Points
    6 967
    Par défaut
    Bon, j'ai suivis tes conseils et les indications de Transactions actives multiples, et ça semble marcher !

    Voici mes composants :

    FDConnection :
    DriverName = IB
    LoginPrompt = False
    Params.Database = la base
    Params.DriverID = IB
    Params.Password = le mdp
    Params.Port = 3050
    Params.Protocol = ipLocal
    Params.UserName = le login
    TxOptions.AutoCommit = False
    TxOptions.AutoStart = False (True, ça marche aussi)
    TxOptions.AutoStop = False
    TxOptions.DisconnectAction = xdRollback
    TxOptions.EnableNested = True
    Transaction = FDTransactionMaj << Et non pas FDTransactionSelect, sinon ça marche pas (je ne comprend pas pourquoi).
    UpdateTransaction = FDTransactionMaj

    FDGUIxWaitCursor

    FDPhysIBDriverLink

    FDTransactionSelect :
    Connection = FDConnection
    Options.AutoCommit = False
    Options.AutoStart = False (True, ça marche aussi)
    Options.AutoStop = False
    Options.DisconnectAction = xdRollback
    Options.EnableNested = True
    Options.Isolation= xiReadCommitted
    Options.ReadOnly = True

    FDTransactionMaj :
    Connection = FDConnection
    Options.AutoCommit = False
    Options.AutoStart = False (True, ça marche aussi)
    Options.AutoStop = False
    Options.DisconnectAction = xdRollback
    Options.EnableNested = True
    Options.Isolation= xiReadCommitted
    Options.ReadOnly = False

    FDQuery (pour les select):
    Connection = FDConnection
    Transaction = FDTransactionSelect

    FDQueryMaj (pour manipulation de données):
    Connection = FDConnection
    UpdateTransaction = FDTransactionMaj

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        // Juste après la connexion.
        FDTransactionSelect.StartTransaction;
        FDTransactionMaj.StartTransaction;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        // A la fin.
        FDTransactionSelect.Commit;
        FDTransactionMaj.Commit;


    Citation Envoyé par Barbibulle Voir le message
    Performance et plus facile à gérer.
    Interbase/firebird utilisent une transaction pour un simple select.
    Personnellement, je ne trouve pas ça "plus facile". Être obligé de monter toute cette usine à gaz, juste pour pouvoir gérer proprement des transactions, moi je trouve ça bien compliqué pour pas grand chose.

    pour ton aide et tes explications.
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai. ___ Écrivez dans un français correct !!

    C++Builder 5 - Delphi 6#2 Entreprise - Delphi 2007 Entreprise - Delphi 2010 Architecte - Delphi XE Entreprise - Delphi XE7 Entreprise - Delphi 10 Entreprise - Delphi 10.3.2 Entreprise - Delphi 10.4.2 Entreprise - Delphi 11.1 Entreprise
    OpenGL 2.1 - Oracle 10g - Paradox - Interbase (XE) - PostgreSQL (15.4)

  12. #12
    Membre expert
    Avatar de Barbibulle
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    2 048
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 2 048
    Points : 3 342
    Points
    3 342
    Par défaut
    Si on utilise les paramètres préconisés c'est très simple et on n' a pas besoin de gérer les transactions (pas besoin de startTransaction ni de Commit).
    Et je comprend qu'on ne puisse pas aimer l'automatisme (puis qu'on a l'impression de ne pas être maître). Mais dès lors qu'on a compris ce qui est fait et que c'est fait correctement, c'est vraiment dommage de s'en priver.

    Cette gestion automatique n’empêche pas lorsque c'est nécessaire (par exemple quand on veut plusieurs updates dans une seule transaction) de pouvoir gérer manuellement la transaction par un start puis commit/rollback.


    Et effectivement ou peut vouloir tout faire manuellement mais le codage sera plus contraignant et pas forcément mieux fait.

  13. #13
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 042
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 67
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 042
    Points : 40 955
    Points
    40 955
    Billets dans le blog
    62
    Par défaut
    Bonjour,

    donc pour te reprendre
    Transaction = FDTransactionMaj << Et non pas FDTransactionSelect, sinon ça marche pas (je ne comprend pas pourquoi).
    UpdateTransaction = FDTransactionMaj
    donc une seule et même transaction suffit . Attention je n'ai pas dit que c'était la bonne solution mais avec ton code j'ai l'impression que FDTransactionSelect ne sert à rien
    Options.AutoStart = False (True, ça marche aussi)
    là , c'est le même comportement que ZEOSDBO dés que tu fait Startransaction autocommit devient false et bien sur cela va de soit un Commit le remet à true.
    il serait d'ailleurs bon de vérifier que si le autocommit est spécifié à false il le reste après le commit (doute, bug récurent avec ZEOS par exemple).

    Reste ensuite l'histoire de ces deux transactions pour une même connection et le nested là , c'est plus complexe et une partie est spécifique Interbase/Firebird
    Citation Envoyé par Dmitry Arefiev
    FireDAC supports multiple simultaneous transactions per single connection through TFDTransaction component. But for that the simultaneous transactions must be supported by a DBMS. At moment only InterBase and Firebird are supporting multiple simultaneous transactions. When a DBMS does not support them, then you can use multiple TFDConnection's.
    http://docwiki.embarcadero.com/RADSt..._%28FireDAC%29
    même en laissant les automatismes je n'ai pas tout compris encore.
    UpdateTransaction : objet transaction par défaut pour toutes les commandes de mise à jour, utilisé pour valider les mises à jour provenant des ensembles de données FireDAC. Notez que l'objet UpdateTransaction ne sera par exemple pas utilisé pour une requête UPDATE explicitement spécifiée pour le composant TFDQuery.
    La connexion semble faire le choix de la transaction en fonction de critères peu expliqués on pourrait s'attendre à ce que seule les lectures soit avec la propriété transaction et le reste avec Updatetransaction, mais ce que j'ai pu lire à ce sujet ne le confirme pas puisque ce choix semble être "écrasé" par les propriétés au niveau de la Query
    MVP Embarcadero
    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Rio, Sidney), D11 (Alexandria), D12 (Athènes)
    SGBD : Firebird 2.5, 3, SQLite
    générateurs États : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Windows 11, Ubuntu, Androïd

  14. #14
    Membre expert
    Avatar de Barbibulle
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    2 048
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : France

    Informations forums :
    Inscription : Octobre 2002
    Messages : 2 048
    Points : 3 342
    Points
    3 342
    Par défaut
    Citation Envoyé par Lung Voir le message
    Transaction = FDTransactionMaj << Et non pas FDTransactionSelect, sinon ça marche pas (je ne comprend pas pourquoi).
    Si ça fonctionne très bien, à partir du moment qu'on n'utilise pas de FDQuery avec une requête Update dedans.

    En gros les query ne doivent contenir que des Select, l'open/execsql... de la query se fait dans la transaction par défaut (sans analyse du type de requête).
    Ces requêtes renvoient donc un ensemble de données qu'on va pouvoir mettre à jour
    soit de manière transparente avec les composants DB
    soit de manière explicite avec un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    FDQuery.Edit;
    ou 
    FDQuery.insert;
    ou 
    FDQuery.delete;
    etc...
    Ces opérations sont quand à elles exécutées dans la UpdateTransaction.

    Bien évidemment parfois on a besoin de faire un update/Insert directement sans avoir à passer par un select.
    Dans ces cas là il suffit d'indiquer sur la query en question d'utiliser la transaction de mise à jour.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    FDQuery.Transaction = FDTransactionMaj;

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

Discussions similaires

  1. Gérer soi même on Submit
    Par riete dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 07/01/2008, 17h30
  2. gérer les transactions avec php/sql server
    Par loukili81 dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 15/05/2007, 17h39
  3. Où gérer les transactions avec Firebird ?
    Par DMO dans le forum Débuter
    Réponses: 2
    Dernier message: 26/04/2005, 09h21
  4. Réponses: 1
    Dernier message: 26/02/2005, 12h55
  5. Les transactions avec Delphi & InterBase
    Par Redhouane dans le forum Bases de données
    Réponses: 5
    Dernier message: 31/12/2004, 15h34

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