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 :

[KBMMemtable+UIB] Sauvegarder les modifications


Sujet :

Bases de données Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Juin 2006
    Messages
    45
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 45
    Par défaut [KBMMemtable+UIB] Sauvegarder les modifications
    Bonsoir,

    J'utilise KBMmemtable et les UIB pour afficher les données d'une table dans une DBGrid. J'arrive à modifier les données mais comment faire pour les sauvegarder dans la base ?

    Merci

  2. #2
    Expert confirmé
    Avatar de Cl@udius
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2006
    Messages
    4 878
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Février 2006
    Messages : 4 878
    Par défaut
    Salut

    Pour pouvoir mettre à jour ta base de données il faut que tu utilises le DeltaHandler et que tu appelles la méthode Resolve de la kbmMemTable.

    Si tu regardes le code source de la classe TkbmCustomDeltaHandler tu verras trois procédures virtual:
    • InsertRecord
    • DeleteRecord
    • ModifyRecord

    Ce sont ces 3 méthodes que tu dois implémenter.

    De plus il faut aussi tenir compte de la propriété EnableVersionning et de la méthode CheckPoint.

    Mais comme un exemple est plus parlant qu'un grand baratin, examine le code suivant.
    Surtout que je n'ai jamais prétendu être un bon pédagogue.

    Dans cet exemple tu retrouves un TJvUIBDataSet qui est lié à ta base de données. Les données sont lues depuis ce DataSet et chargées dans la kbmMemTable. (je passe la-dessus tu sais le gérer ).

    Tu trouveras également la définition de la classe TDeltaHandler, et l'implémentation des trois procédures de mise à jour.

    L'appel de la méthode Resolve est appelée à chaque Post ou Delete sur la MemTable (ce n'est pas obligé, tu peux résoudre d'un coup toute une série de mises à jour).

    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
     
    unit Unit1;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, DB, kbmMemTable, JvUIBDataset, JvUIB, JvUIBLib;
     
    type
      TDeltaHandler = class(TkbmCustomDeltaHandler)
      private
        procedure ExecSQLStatement(const SQLText: string);
      protected
        { Déclarations protégées }
        procedure InsertRecord(var Retry: Boolean; var State: TUpdateStatus); override;
        procedure DeleteRecord(var Retry: Boolean; var State: TUpdateStatus); override;
        procedure ModifyRecord(var Retry: Boolean; var State: TUpdateStatus); override;
      end;
     
      TForm1 = class(TForm)
        kbmMemTable1: TkbmMemTable;
        JvUIBDataSet1: TJvUIBDataSet;
        UIB_DB: TJvUIBDataBase;
        trRead: TJvUIBTransaction;
        trWrite: TJvUIBTransaction;
        procedure FormCreate(Sender: TObject);
        procedure kbmMemTable1AfterPostAndDelete(DataSet: TDataSet);
      private
        { Déclarations privées }
        FDeltaHandler: TDeltaHandler;
        procedure ResolveMemTable;
      public
        { Déclarations publiques }
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    {$R *.dfm}
     
    { Form1 }
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      // Création du DeltaHandler
      FDeltaHandler := TDeltaHandler.Create(self);
      FDeltaHandler.DataSet := kbmMemTable1;
     
      // Démarrage de la transaction de lecture
      trRead.StartTransaction;
      // Ouverture du DataSet
      JvUIBDataSet1.Open;         // Optionnel: car effectué lors du LoadFromDataSet
      // Charger la memory table
      kbmMemTable1.LoadFromDataSet(JvUIBDataSet1, [mtcpoStructure, mtcpoProperties]);
      // Fermeture du DataSet
      JvUIBDataSet1.OnClose := etmCommit;
      JvUIBDataSet1.Close;  // commit de la transaction effectué
     
      // Activer le versioning
      kbmMemTable1.EnableVersioning := True;
      // Effectuer un checkpoint
      kbmMemTable1.CheckPoint;
    end;
     
    procedure TForm1.ResolveMemTable;
    var
      SavePlace: TBookmark;
    begin
      with kbmMemTable1 do begin
        // Si le DeltaHandler n'est pas défini: sortir
        if not Assigned(DeltaHandler) then Exit;
        // Si les données ont été modifiées
        if IsDataModified then
        begin
          SavePlace := GetBookmark;     // Où suis-je
          DisableControls;
          try
            DeltaHandler.Resolve;       // Résolution des modifications
            CheckPoint;                 // Actualisation du CheckPoint;
            if BookMarkValid(SavePlace) then
              GotoBookmark(SavePlace);  // Retour à ma place
          finally
            FreeBookmark(SavePlace);
            EnableControls;
          end;
          // Actualiser le checkpoint
          CheckPoint;
        end;
      end;
    end;
     
    procedure TForm1.kbmMemTable1AfterPostAndDelete(DataSet: TDataSet);
    begin
      // Résoudre les modifs
      ResolveMemTable;
    end;
     
    { TDeltaHandler }
    procedure TDeltaHandler.ExecSQLStatement(const SQLText: string);
    var
      Query: TJvUIBQuery;
    begin
      Query := TJvUIBQuery.Create(nil);
      try
        Query.DataBase := Form1.UIB_DB;
        Query.Transaction := Form1.trWrite;
        Query.Transaction.StartTransaction;
     
        Query.SQL.Text := SQLText;
        try
          Query.ExecSQL;
          Query.Close(etmCommit);
        except
          on E: EUIBError do
            MessageDlg('Erreur n° ' + IntToStr(E.ErrorCode) + #13#10#13#10 +
                        E.Message,
                        mtError, [mbOK], 0);
          else
            raise;
          Query.Close(etmRollback);
        end;
      finally
        Query.Free;
      end;
    end;
     
    procedure TDeltaHandler.InsertRecord(var Retry: Boolean; var State: TUpdateStatus);
    begin
      // Requête Insert
      ExecSQLStatement('INSERT INTO MaTable ... VALUES ...');
    end;
     
    procedure TDeltaHandler.DeleteRecord(var Retry: Boolean; var State: TUpdateStatus);
    begin
      // Requête Update
      ExecSQLStatement('UPDATE MaTable SET ... WHERE ...');
    end;
     
    procedure TDeltaHandler.ModifyRecord(var Retry: Boolean; var State: TUpdateStatus);
    begin
      // Requête Delete
      ExecSQLStatement('DELETE FROM MaTable WHERE ...');
    end;
     
     
    end.
    Si tu as besoin de plus d'infos, n'hésite pas à me demander.

    Si ça t'intéresse je me suis créé un composant kbmDeltaHandler que je pose sur ma fiche et que je lie à la kbmMemTable où les 3 méthodes de mises à jour se chargent automatiquement de renseigner les requêtes SQL Insert Update et Delete, ainsi qu'une méthode Refresh de l'enregistrement courant.

    Bonne lecture
    @+ Claudius

  3. #3
    Membre confirmé
    Inscrit en
    Juin 2006
    Messages
    45
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 45
    Par défaut
    Merci Claudius40 pour ta réponse très instructive. Peux tu m'envoyer le composant sur anouar at softhome dot net ?

    Merci

  4. #4
    Expert confirmé
    Avatar de Cl@udius
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2006
    Messages
    4 878
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Février 2006
    Messages : 4 878
    Par défaut
    Salut

    Je peux mettre les sources sur le forum. Je pense que cela peut servir à d'autres !!
    D'ac ?

    @+

  5. #5
    Membre confirmé
    Inscrit en
    Juin 2006
    Messages
    45
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 45
    Par défaut
    C'est encore mieux

  6. #6
    Expert confirmé
    Avatar de Cl@udius
    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2006
    Messages
    4 878
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Février 2006
    Messages : 4 878
    Par défaut
    Re,

    Alors voilà !

    Le composant TkbmDeltaHandler.
    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
     
    unit kbmDeltaHandler;
     
    interface
     
    uses
      SysUtils, Classes, DB, DBTables, kbmMemTable, JvUIB;
     
    type
      TkbmDeltaHandler = class(TkbmCustomDeltaHandler)
      private
        FDataBase: TJvUIBDataBase;
        FTransaction: TJvUIBTransaction;
        FTableName: string;
        FPrimaryIndexFields: string;
        { Déclarations privées }
        function VariantToStr(ADataType: TFieldType; AValue: Variant): string;
        function BuildWhereWithPKFields: string;
      protected
        { Déclarations protégées }
        procedure InsertRecord(var Retry: Boolean; var State: TUpdateStatus); override;
        procedure DeleteRecord(var Retry: Boolean; var State: TUpdateStatus); override;
        procedure ModifyRecord(var Retry: Boolean; var State: TUpdateStatus); override;
      public
        { Déclarations publiques }
      published
        { Déclarations publiées }
        property Database: TJvUIBDataBase read FDataBase write FDataBase;
        property Transaction: TJvUIBTransaction read FTransaction write FTransaction;
        property TableName: string read FTableName write FTableName;
        property PrimaryIndexFields: string read FPrimaryIndexFields write FPrimaryIndexFields;
      end;
     
    procedure Register;
     
    implementation
     
    uses
      Variants, JvUIBLib{, Dialogs};
     
     
    procedure Register;
    begin
      RegisterComponents('kbmMemTable', [TkbmDeltaHandler]);
    end;
     
    //------------------------------------------------------------------------------
    // TkbmDeltaHandler
    //------------------------------------------------------------------------------
    //------------------------------------------------------------------------------
    function TkbmDeltaHandler.VariantToStr(ADataType: TFieldType; AValue: Variant): string;
    begin
      // NOTA: Tous les types de champ n'ont pas été traités.
     
      if VarIsNull(AValue) then
        result := 'NULL'
      else if ADataType in kbmStringTypes then
        result := QuotedStr(AValue)
      else if ADataType in [ftDate, ftTime, ftDateTime, ftTimeStamp] then
        result := QuotedStr(DateTimeToStr(AValue))
      else if ADataType in [ftSmallInt, ftInteger] then
        result := IntToStr(AValue)
      else if ADataType in [ftFMTBcd, ftBCD, ftCurrency] then
        result := FloatToStr(AValue)
      else
        result := 'NULL';
     
    end;
    //------------------------------------------------------------------------------
    function TkbmDeltaHandler.BuildWhereWithPKFields: string;
    var
      i: integer;
      pkf, fn: string;
      //---------------------------------------------
      function FieldDataType(fn: string): TFieldType;
      var
        i: integer;
      begin
        i := 0;
        Result := ftUnknown;
        repeat
          if (FieldNames[i] = fn) then Result := Fields[i].DataType;
          Inc(i);
        until (Result <> ftUnknown) or (i = FieldCount);
      end;
      //---------------------------------------------
    begin
      Result := ' WHERE ';
      pkf := FPrimaryIndexFields;
      if Length(pkf) = 0 then Exit;
     
      fn := '';
      i := 1;
      repeat
        fn := fn + pkf[i];
        if (i = Length(pkf)) or (pkf[i+1] = ';') then
        begin
          Result := Result + fn + ' = ' +
                    VariantToStr(FieldDataType(fn), OrigValuesByName[fn]);
          if i < Length(pkf) then Result := Result + ' AND ';
          fn := '';
        end;
        Inc(i);
        if (pkf[i] = ';') then Inc(i);
      until (i > Length(pkf));
    end;
    //------------------------------------------------------------------------------
    procedure DisplayErrMessage(ErrorCode: Integer; Msg: string);
    begin
      case ErrorCode of
        32: // Droits d'accès
          Msg := 'Vous ne disposez des prérogatives nécessaires pour ' + #13#10 +
                 'accéder ou modifier ces données.';
      end;
      MessageDlg('Erreur n° ' + IntToStr(ErrorCode) + #13#10#13#10 +
                 Msg,
                 mtWarning, [mbOK], 0);
    end;
    //------------------------------------------------------------------------------
    procedure TkbmDeltaHandler.ModifyRecord(var Retry: Boolean; var State: TUpdateStatus);
    var
      i: integer;
      Query: TJvUIBQuery;
      SQLText: string;
      oldDateFormat: string;
      oldDecSep: Char;
    begin
      // Save actual date format
      oldDateFormat := ShortDateFormat;
      ShortDateFormat := 'mm/dd/yyyy';    // Pour DateTimeToStr
      // Save actual decimal separator
      oldDecSep := DecimalSeparator;
      DecimalSeparator := '.';            // Pour FloatToStr
     
      // Création de la requête Update
      Query := TJvUIBQuery.Create(nil);
      try
        Query.DataBase := Database;
        Query.Transaction := Transaction;
        Query.Transaction.StartTransaction;
     
        SQLText := 'UPDATE ' + TableName + ' SET ';
        for i := 0 to FieldCount - 1 do begin
          if Fields[i].FieldKind = fkData then
          begin
            if (SQLText <> 'UPDATE ' + TableName + ' SET ') and
               (Fields[i].FieldKind = fkData) then
              SQLText := SQLText + ', ';
            SQLText := SQLText + FieldNames[i] + '=' +
                       VariantToStr(Fields[i].DataType, Values[i]);
          end;
        end;
        SQLText := SQLText + BuildWhereWithPKFields;
        Query.SQL.Text := SQLText;
        try
          //ShowMessage(Query.SQL.Text);
          Query.Prepare;
          Query.ExecSQL;
          Query.Close(etmCommit);
        except
          on E: EUIBError do
            DisplayErrMessage(E.ErrorCode, E.Message);
          else
            raise;
          Query.Close(etmRollback);
        end;
      finally
        Query.Free;
      end;
      // Restore original date format and Decimal separator
      ShortDateFormat := oldDateFormat;
      DecimalSeparator := oldDecSep;
    end;
    //------------------------------------------------------------------------------
    procedure TkbmDeltaHandler.InsertRecord(var Retry: Boolean; var State: TUpdateStatus);
    var
      i: integer;
      Query: TJvUIBQuery;
      SQLText: string;
      oldDateFormat: string;
      oldDecSep: Char;
    begin
      // Sauvegarder le format de date courant
      oldDateFormat := ShortDateFormat;
      ShortDateFormat := 'mm/dd/yyyy';    // Pour DateTimeToStr
      // Sauvegarde le séparateur décimal courant
      oldDecSep := DecimalSeparator;
      DecimalSeparator := '.';            // Pour FloatToStr
     
      // Création de la requête Insert
      Query := TJvUIBQuery.Create(nil);
      try
        Query.DataBase := Database;
        Query.Transaction := Transaction;
        Query.Transaction.StartTransaction;
     
        SQLText := 'INSERT INTO ' + TableName + ' VALUES(';
        for i := 0 to FieldCount - 1 do begin
          if Fields[i].FieldKind = fkData then
          begin
            if (SQLText <> 'INSERT INTO ' + TableName + ' VALUES(') and
               (Fields[i].FieldKind = fkData) then
              SQLText := SQLText + ', ';
            SQLText := SQLText + VariantToStr(Fields[i].DataType, Values[i]);
          end;
        end;
        SQLText := SQLText + ')';
        Query.SQL.Text := SQLText;
        try
          //ShowMessage(Query.SQL.Text);
          Query.ExecSQL;
          Query.Close(etmCommit);
        except
          on E: EUIBError do
            MessageDlg('Erreur n° ' + IntToStr(E.ErrorCode) + #13#10#13#10 +
                        E.Message,
                        mtError, [mbOK], 0);
          else
            raise;
          Query.Close(etmRollback);
        end;
      finally
        Query.Free;
      end;
      // Restaurer les formats initiaux
      ShortDateFormat := oldDateFormat;
      DecimalSeparator := oldDecSep;
    end;
    //------------------------------------------------------------------------------
    procedure TkbmDeltaHandler.DeleteRecord(var Retry: Boolean; var State: TUpdateStatus);
    var
      Query: TJvUIBQuery;
    begin
      // Création de la requête Delete
      Query := TJvUIBQuery.Create(nil);
      try
        Query.DataBase := Database;
        Query.Transaction := Transaction;
        Query.Transaction.StartTransaction;
     
        Query.SQL.Text := 'DELETE FROM ' + TableName + ' ' +
                          BuildWhereWithPKFields;
        try
          //ShowMessage(Query.SQL.Text);
          Query.Prepare;
          Query.ExecSQL;
          Query.Close(etmCommit);
        except
          on E: EUIBError do
            MessageDlg('Erreur n° ' + IntToStr(E.ErrorCode) + #13#10#13#10 +
                        E.Message,
                        mtError, [mbOK], 0);
          else
            raise;
          Query.Close(etmRollback);
        end;
      finally
        Query.Free;
      end;
    end;
    //------------------------------------------------------------------------------
    end.
    Tu peux voir que 4 propriétés sont publiées:

    Database, la base de données sur laquelle tu travailles
    Transaction, la transaction que tu vas utiliser pour faire tes mises à jour.
    TableName: La table que tu vas mettre à jour
    et enfin PrimaryIndexFields, la liste du ou des champs qui composent ta clé primaire. Cette propriété est utilisée pour construire la clause WHERE lors d'un UPDATE ou DELETE. Si plusieurs champs composent ta clé primaire sépare les par des points virgules ( ; ), exemple: 'ID;NUM_LIGNE'

    Utilisation: Tu poses le compo kbmDeltaHandler sur ta fiche, tu renseignes les 4 propriétés. Ensuite tu relies ta kbmMemTable au DeltaHandler via sa propriété DelaHandler.

    Voilà. Je n'ai pas la prétention de dire que ce compo est parfait mais il fonctionne correctement. Libre à toi de le modifier ou de l'améliorer pour tes propres besoins.

    Je te prépare également le source d'un compo nommé TkbmMemoryTable qui hérité de TkbmMemTable, dans lequel j'ai implémenté une méthode de rafraîchissement de l'enregistrement courant.

    @+ Claudius.

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

Discussions similaires

  1. editer un message dans un pop up et sauvegarder les modifs
    Par sallemel dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 29/01/2009, 11h44
  2. ouvrir et fermer un fichier excel en sauvegardant les modifications.
    Par decoalaa dans le forum Macros et VBA Excel
    Réponses: 16
    Dernier message: 17/10/2008, 15h37
  3. Réponses: 2
    Dernier message: 11/10/2008, 18h05
  4. Sauvegarder les modifications sur une variable
    Par maaike dans le forum VBA Access
    Réponses: 5
    Dernier message: 21/08/2007, 23h28
  5. Réponses: 6
    Dernier message: 30/05/2006, 22h41

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