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 :

[Tutoriel] Découvrez comment développer un Dataset en mémoire


Sujet :

Bases de données Delphi

  1. #1
    Rédacteur
    Avatar de Pedro
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    5 411
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 5 411
    Points : 8 078
    Points
    8 078
    Par défaut [Tutoriel] Découvrez comment développer un Dataset en mémoire
    Bonjour à tous

    Franck Soriano nous propose un nouveau tutoriel qui vous fera découvrir comment optimiser vos accès aux base de données en créant un Dataset entièrement en mémoire.

    Un DataSet en mémoire. Encore un ! Ce type de composant fait légion sur le net. Même Delphi intègre le TClientDataSet en standard qui peut faire office de DataSet en mémoire.

    Alors pourquoi vouloir en développer un de plus ? Tout simplement pour trois raisons majeures :


    • Malgré tous les composants existants, je n'en ai jamais trouvé un seul qui ait le niveau de performances que j'attends. Comme je l'ai expliqué dans le précédent article, le TClientDataSet est très lourd, avec une architecture complexe. On ne dispose d'aucun moyen permettant de le charger efficacement.
    • Le TDataSet est au coeur de toute application base de données en Delphi. Si on veut écrire des applications performantes, il est important de comprendre les mécanismes mis en oeuvre dans son implémentation. De cette manière, lorsqu'on écrit une ligne de code, on appréhende mieux ses conséquences. Ecrire un DataSet en mémoire est un très bon prétexte pour étudier son fonctionnement.
    • Enfin, on aura besoin de surcharger un TDataSet dans les prochains articles afin de s'interfacer avec OLEDB.
    Bonne lecture!
    Pedro
    Aucune réponse aux sollicitations techniques par MP

    Faut pas attendre d'en avoir besoin pour s'en servir... (Lucien Stéphane)

    Les pages Source C'est bon. Mangez-en!
    Le défi Delphi
    Règles du forum - FAQ Delphi - Pensez au chtit
    Aéroclub Bastia Saint-Exupéry

  2. #2
    Membre chevronné Avatar de chaplin
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 215
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 215
    Points : 1 819
    Points
    1 819
    Par défaut
    Un vrai travail de fourmis , mais extraordinaire dans la démarche. .
    Tu devrais être embauché dans l'équipe R&D de Codegear.

  3. #3
    Membre émérite
    Homme Profil pro
    Directeur technique
    Inscrit en
    Mai 2008
    Messages
    2 401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2008
    Messages : 2 401
    Points : 2 304
    Points
    2 304
    Par défaut
    Salut;

    + 1 chaplin.
    Toutes mes félicitations Franck Soriano juste une toute petite reproche; fallait terminer ça par la réalisation d'un composant !
    Bon courage ou Bonne Chance (selon le contexte)
    Mon blog sur WordPress

  4. #4
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Merci à vous.

    fallait terminer ça par la réalisation d'un composant !
    Zut, j'ai pas dû être assez clair alors. Tout le tuto décrit justement le contenu du composant (enfin de la classe). Et la classe complète se trouve dans les sources qu'on peut télécharger...

  5. #5
    Membre émérite
    Homme Profil pro
    Directeur technique
    Inscrit en
    Mai 2008
    Messages
    2 401
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Directeur technique
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2008
    Messages : 2 401
    Points : 2 304
    Points
    2 304
    Par défaut
    Re;

    Zut, j'ai pas dû être assez clair alors. Tout le tuto décrit justement le contenu du composant (enfin de la classe)
    faut avouer quand même qu'il y a une différence entre classe et composant, au moins au niveau de l'utilisation ; le composant peut-être utilisé par d'autres langages.

    Mais l'idée est assez originale! Bravo
    Bon courage ou Bonne Chance (selon le contexte)
    Mon blog sur WordPress

  6. #6
    Membre émérite Avatar de edam
    Homme Profil pro
    Développeur Delphi/c++/Omnis
    Inscrit en
    Décembre 2003
    Messages
    1 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur Delphi/c++/Omnis
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 894
    Points : 2 771
    Points
    2 771
    Par défaut
    merci
    c'est que c'est un autre composant, mais, l'essentiel c'est l'explication données
    encore merci
    note :j'ai arrêté d'utiliser TClientDataset, j'ai passé à RXMemoryData, mais je crois que je vais essayer de comprendre mieux ta class, pour l'utiliser dans mes prochain projet
    PAS DE DESTIN, C'EST CE QUE NOUS FAISONS

  7. #7
    Candidat au Club
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Août 2006
    Messages : 3
    Points : 4
    Points
    4
    Par défaut Optimisation des accès BD par Franck Soriano
    Je suis vraiment admiratif devant la qualité des articles de Franck Soriano et je suis impatient de lire le suivant! N'étant pas moi-même capable de mettre en oeuvre le TmemoryDataset dans une application concrète, j'espère trouver par la suite un exemple pratique dans lequel ce bijou est exploité (connexion et requêtes avec SQL server, Access ou MySql).

    Merci beaucoup.

  8. #8
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Merci.

    La suite est bien avancée. J'y présenterai l'utilisation de OLEDB avec SQL Server. Mais c'est pareil avec n'importe quel SGBD, du moment que ce dernier fournit un provider OLEDB.
    Même... Excel...

  9. #9
    Membre émérite Avatar de edam
    Homme Profil pro
    Développeur Delphi/c++/Omnis
    Inscrit en
    Décembre 2003
    Messages
    1 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur Delphi/c++/Omnis
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 894
    Points : 2 771
    Points
    2 771
    Par défaut
    bon courage alors,
    PAS DE DESTIN, C'EST CE QUE NOUS FAISONS

  10. #10
    Membre émérite Avatar de edam
    Homme Profil pro
    Développeur Delphi/c++/Omnis
    Inscrit en
    Décembre 2003
    Messages
    1 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur Delphi/c++/Omnis
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 894
    Points : 2 771
    Points
    2 771
    Par défaut
    salut, alors, quoi de neuf???
    PAS DE DESTIN, C'EST CE QUE NOUS FAISONS

  11. #11
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Ben la suite a été annoncée hiers...

  12. #12
    Membre émérite Avatar de edam
    Homme Profil pro
    Développeur Delphi/c++/Omnis
    Inscrit en
    Décembre 2003
    Messages
    1 894
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur Delphi/c++/Omnis
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 894
    Points : 2 771
    Points
    2 771
    Par défaut
    merci, je l'avais vu,
    PAS DE DESTIN, C'EST CE QUE NOUS FAISONS

  13. #13
    Futur Membre du Club
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    8
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 8
    Points : 9
    Points
    9
    Par défaut
    Bonjour,
    j'ai récupéré le source fourni avec l'article mais j'ai quelques soucis pour le faire fonctionner avec des blobs...

    la variable FBlobFields a été confondue avec FBLobList à plusieurs endroits, exemple :

    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
    // Remplace les LOB du buffer <Buffer> par une copie de leur valeur.
    procedure TMemoryDataSet.CopyBufferBlob(Buffer: PChar);
    var
      FieldNo : cardinal;
      Offset : Cardinal;
      Data : PFieldData;
      Valeur, ValeurDest,
      size : cardinal;
      ptr : pointer;
      i : integer;
    begin
      for i := 0 to FBlobFields.Count - 1 do // FBLobList.Count -1 do
      begin
        FieldNo := cardinal(FBlobFields[i]); // FBLobList[i]);
        Offset := FFieldInfo[FieldNo-1].Offset;
        Data := GetPFieldData(Buffer, Offset);
        if not IsNull(Data)
        then begin
          // On lit la valeur et la taille du LOB à copier.
          Valeur := cardinal(Data.Data[0]);
          size := Data.LengthValue;
     
          // On alloue un nouveau LOB pour la copie.
          ValeurDest := AllocBlob;
     
          // Copie de la valeur.
          GetMem(ptr, Size);
          move(FBlobList[Valeur]^, ptr^, size);
          FBlobList[ValeurDest] := ptr;
     
          // On affecte la nouvelle valeur au champ destination.
          move(ValeurDest, Data.Data[0], sizeof(ValeurDest));
        end;
      end;
    end;
    Un autre bout de code qui peut poser problème :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    constructor TMemoryBlobStream.Create(Field: TField; Mode: TBlobStreamMode);
    begin
      // On commence par mémoriser les paramètres de création.
      FDataSet := TMemoryDataSet(Field.DataSet);
      FMode := Mode;
     
      // On lit les informations du champ pour lequel on veut accéder au LOB.
      FLineBuf := FDataSet.GetActiveBuffer;
      if not Assigned(FLineBuf) then Exit; // ligne ajoutée
      FieldOffset := FDataSet.FFieldInfo[Field.FieldNo-1].Offset;
    En effet, si on ouvre un dataset vide, GetActiveBuffer ne renvoi rien...

  14. #14
    Expert confirmé

    Profil pro
    Leader Technique
    Inscrit en
    Juin 2005
    Messages
    1 756
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

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

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 756
    Points : 4 170
    Points
    4 170
    Par défaut
    Merci pour ces retours.

    En effet, comme tu as remarqué FBLobList est utilisé à la place FBlobFields à plusieurs endroits.
    J'intégrerais tes corrections pour une prochaine version.

    En attendant, voici les méthodes à corriger :

    CopyBufferBlob
    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
     
    procedure TMemoryDataSet.CopyBufferBlob(Buffer: PChar);
    var
      FieldNo : cardinal;
      Offset : Cardinal;
      Data : PFieldData;
      Valeur, ValeurDest,
      size : cardinal;
      ptr : pointer;
      i : integer;
    begin
      for i := 0 to FBlobFields.Count -1 do
      begin
        FieldNo := cardinal(FBlobFields[i]);
        Offset := FFieldInfo[FieldNo-1].Offset;
        Data := GetPFieldData(Buffer, Offset);
        if not IsNull(Data)
        then begin
          // On lit la valeur et la taille du LOB à copier.
          Valeur := cardinal(Data.Data[0]);
          size := Data.LengthValue;
     
          // On alloue un nouveau LOB pour la copie.
          ValeurDest := AllocBlob;
     
          // Copie de la valeur.
          GetMem(ptr, Size);
          move(FBlobList[Valeur]^, ptr^, size);
          FBlobList[ValeurDest] := ptr;
     
          // On affecte la nouvelle valeur au champ destination.
          move(ValeurDest, Data.Data[0], sizeof(ValeurDest));
        end;
      end;
    end;
    ReleaseBufferBlob
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    procedure TMemoryDataSet.ReleaseBufferBlob(Buffer : PChar);
    var
      i: Integer;
      FieldNo: Integer;
    begin
      for i := 0 to FBlobFields.Count - 1 do
      begin
        FieldNo := integer(FBlobFields[i]);
        ReleaseBlob(Cardinal(GetPFieldData(Buffer,
          FFieldInfo[FieldNo - 1].Offset).Data[0]));
      end;
    end;
    CloneBuffer
    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
     
    procedure TMemoryDataSet.CloneBuffer(Source, Dest : PChar);
    var
      i : integer;
      FieldNo : integer;
      Valeur : cardinal;
      Offset : cardinal;
      ValeurDest : cardinal;
      ptr : pointer;
      size : cardinal;
      Data : PFieldData;
      DestData : PFieldData;
    begin
      // Dans un premier temps, on fait une copie du buffer.
      move(Source^, Dest^, RecordSize);
     
      // Ensuite, il faut dupliquer tous les LOB du buffer.
      CopyBufferBlob(Dest);
     
      for i := 0 to FBlobFields.Count -1 do
      begin
        FieldNo := cardinal(FBlobFields[i]);
        Offset := FFieldInfo[FieldNo-1].Offset;
        Data := GetPFieldData(Source, Offset);
        if not IsNull(Data)
        then begin
          // On lit la valeur et la taille du LOB à copier.
          Valeur := cardinal(Data.Data[0]);
          size := Data.LengthValue;
     
          // On alloue un nouveau LOB pour la copie.
          ValeurDest := AllocBlob;
     
          // Copie de la valeur.
          GetMem(ptr, Size);
          move(FBlobList[Valeur]^, ptr^, size);
          FBlobList[ValeurDest] := ptr;
     
          // On affecte la nouvelle valeur au champ destination.
          DestData := GetPFieldData(Dest, offset);
          move(ValeurDest, DestData.Data[0], sizeof(ValeurDest));
        end;
      end;
    end;
    TMemoryBlobStream.Create
    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
     
    constructor TMemoryBlobStream.Create(Field: TField; Mode: TBlobStreamMode);
    begin
      // On commence par mémoriser les paramètres de création.
      FDataSet := TMemoryDataSet(Field.DataSet);
      FMode := Mode;
     
      // On lit les informations du champ pour lequel on veut accéder au LOB.
      FLineBuf := FDataSet.GetActiveBuffer;
      FieldOffset := FDataSet.FFieldInfo[Field.FieldNo-1].Offset;
     
      // Dans le cas où le dataset est vide, GetActiveBuffer retourne nil. Il faut traiter ce cas comme
      // si le champ est à null.
      if Assigned(FLineBuf)
      then begin
        FFieldData := GetPFieldData(FLineBuf, FieldOffset);
        FBlobIdx := cardinal(FFieldData.Data);;
      end
      else begin
        FFieldData := nil;
        FBlobIdx := 0;
      end;
     
      // Maintenant, le mode d'accès demandé determine la suite des traitements
      case Mode of
      bmRead: // Lecture seul.
        begin
          // On doit juste retourner un flux en lecture seule. Dans ce cas, il suffit
          // d'initialiser les paramètres de lecture.
          if not Assigned(FFieldData) or IsNull(FFieldData)
          then FSize := 0 // Pour les champs NULL, on doit retourner un flux de
                          // longueur 0.
          else begin
            // Le champ existe, on initialise la taille et le buffer à lire.
            // Les LOB sont stockés indirectement. Le champ contient le numéro du
            // tampon dans FBlobList.
            FBlobData := FDataSet.FBlobList[FBlobIdx];
     
            // La taille du LOB est donnée par la longueur courante du champ.
            FSize := FFieldData.LengthValue;
          end;
        end;
      bmWrite, bmReadWrite: // Le mode bmReadWrite n'est pas supporté. Il est traité
        begin               // Comme un write et tronque le champ.
          if not Assigned(FLineBuf)
          then Raise MemoryDataSetException.Create('Erreur interne. ActiveRecord n''est pas définit');
     
          // On doit pouvoir écrire le champ. Ca signifie que si le champ est à NULL
          // il faut créer un nouveau tampon de données.
          if IsNull(FFieldData)
          then begin
            FBlobData := nil; // Pour l'instant le buffer n'est pas défini.
            FBlobIdx := FDataSet.AllocBlob; // On demande au dataset de réserver
                                            // un emplacement pour le LOB.
     
            // On définit la valeur du champ sur le nouveau LOB.
            FFieldData.NullStatus := DBNOTNULL_VALUE;
            FFieldData.LengthValue := 0;
            move(FBlobIdx, FFieldData.Data[0], sizeof(FBlobIdx));
          end
          else begin
            // Le champ existe, on initialise la taille et le buffer à lire.
            // Les LOB sont stockés indirectement. Le champ contient le numéro du
            // tampon dans FBlobList.
     
            // On vide le LOB qui va être réécrit.
            Freemem(FDataSet.FBlobList[FBlobIdx]);
            FDataSet.FBlobList[FBlobIdx] := nil;
            FBlobData := nil;
            FSize := 0;
            FFieldData.LengthValue := 0;
          end;
        end;
      end;
    end;
    Et enfin GetRecord (on obtient une erreur si on fait un Cancel sur un dataset vide).
    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
     
    function TMemoryDataSet.GetRecord(Buffer: PChar; GetMode: TGetMode;
      DoCheck: Boolean): TGetResult;
    var
      TempBuf : PChar;
    {$IFDEF TRACE}
      currentTime : int64;
    {$ENDIF}
     
    begin
    {$IFDEF TRACE}
      GenericLogger.TraceBegin(EVENT_START, 'GetRecord', currentTime, TRACE_LEVEL_VERBOSE);
      try
    {$ENDIF}
        // Premièrement, il faut rechercher l'enregistrement en fonction du mode de déplacement demandé.
        case GetMode of
        gmCurrent: // On veut l'enregistrement courant.
          begin
            if (FCursor >-1)
            then dec(FCursor);   // on remonte d'un enregistrement
            FindNextRecord; // et on recherche l'enregistrement suivant
          end;
        gmPrior: // On veut l'enregistrement précédent.
          FindPriorRecord;
        gmNext: // On veut l'enregistrement suivant.
          FindNextRecord;
        end;
     
        // A présent, il faut vérifier si on se trouve au début ou à la fin du DataSet
        if (FCursor <0) // On se trouve au début, il faut renvoyer BOF.
        then result := grBOF
        else begin
          if FCursor>=integer(FLineIndex.Count) // On se trouve à la fin, on retourne EOF.
          then result := grEOF
          else begin // L'enregistrement existe, on lit le buffer.
            TempBuf := FLineIndex[FCursor];
            move(TempBuf^, Buffer^, RecordSize);
            PLineBuffer(Buffer).BkFlags := bfCurrent; // L'enregistrement est valide
            GetCalcFields(Buffer); // C'est le moment de calculer les champs calculés.
            result := grOK;
          end;
        end;
    {$IFDEF TRACE}
      finally
        GenericLogger.TraceEnd(EVENT_END, 'GetRecord', currentTime, TRACE_LEVEL_VERBOSE);
      end;
    {$ENDIF}  
    end;

  15. #15
    Nouveau Candidat au Club
    Profil pro
    Inscrit en
    Mai 2010
    Messages
    1
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mai 2010
    Messages : 1
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par Franck SORIANO Voir le message
    Merci pour ces retours.

    En effet, comme tu as remarqué FBLobList est utilisé à la place FBlobFields à plusieurs endroits.
    J'intégrerais tes corrections pour une prochaine version.

    En attendant, voici les méthodes à corriger :
    Salutations Franck!!
    Merci pour cet article extraordinaire, et aussi pour la license libérale du code, je compte utiliser ton composant dans plusieurs de mes projets dorénavant!! Ton code est claire, bien commenté, et semble facile à utiliser, on pourrait rien demander de mieux.

    p.s: Si tu peux mettre en ligne la version corrigée, ca serait apprécié, autrement, je dois avoir une version locale avec les corrections incluses, ce qui est plus difficile a gérér!

    Merci encore!
    Carl Eric Codère

  16. #16
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 104
    Points : 112
    Points
    112
    Par défaut Un petit problème sur ReleaseBufferBlob
    Bonjour

    Moi même assez mécontent de la lourdeur du TClientDataSet, je cherchais un dataset en mémoire léger. J'ai un peu joué avec le DataSet proposé par Franck SORIANO. J'en suis satisfait. C'est du bon boulot et c'est bien documenté.

    Je pense avoir détecté une anomalie sur la méthode ReleaseBufferBlob qui ne vérifie pas si le blob est vide avant d'essayer d'en supprimer l'allocation mémoire. Le problème se produit par exemple si l'on modifie un enregistrement en renseignant un champ ftMemo qui n'était pas initialisé au préalable. On lève alors l'exception "Erreur de lecture de flux" lors du changement d'enregistrement.

    Je propose la correction suivante :
    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
    procedure TMemoryDataSet.ReleaseBufferBlob(Buffer : PChar);
    var
      i: Integer;
      FieldNo: Integer;
      PFD: PFieldData;
    begin
      for i := 0 to FBlobFields.Count - 1 do
      begin
        FieldNo := Integer(FBlobFields[i]);
        PFD := GetPFieldData(Buffer, FFieldPos[FieldNo - 1].Offset);
        if Not IsNull(PFD) then
          ReleaseBlob(Cardinal(PFD.Data[0]));
      end;
    end;
    En espérant que ça puisse aider.

    Cordialement

  17. #17
    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
    Bonjour,

    le code source n'est plus disponible ? j'ai une erreur 404

    https://fsoriano.developpez.com/arti...oryDataSet.zip
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  18. #18
    Community Manager

    Avatar de Malick
    Homme Profil pro
    Community Manager
    Inscrit en
    Juillet 2012
    Messages
    9 133
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Community Manager
    Secteur : Conseil

    Informations forums :
    Inscription : Juillet 2012
    Messages : 9 133
    Points : 83 975
    Points
    83 975
    Billets dans le blog
    15
    Par défaut
    Bonjour,

    Citation Envoyé par Paul TOTH Voir le message
    le code source n'est plus disponible ? j'ai une erreur 404
    https://fsoriano.developpez.com/arti...oryDataSet.zip
    C'est corrigé.

    Merci pour le signalement
    Vous avez envie de contribuer au sein du Club Developpez.com ? Contactez-nous maintenant !
    Vous êtes passionné, vous souhaitez partager vos connaissances en informatique, vous souhaitez faire partie de la rédaction.
    Il suffit de vous porter volontaire et de nous faire part de vos envies de contributions :
    Rédaction d'articles/cours/tutoriels, Traduction, Contribution dans la FAQ, Rédaction de news, interviews et témoignages, Organisation de défis, de débats et de sondages, Relecture technique, Modération, Correction orthographique, etc.
    Vous avez d'autres propositions de contributions à nous faire ? Vous souhaitez en savoir davantage ? N'hésitez pas à nous approcher.

Discussions similaires

  1. Comment Développer en équipe ?
    Par christ_mallet dans le forum Débats sur le développement - Le Best Of
    Réponses: 45
    Dernier message: 19/11/2007, 00h15
  2. Réponses: 1
    Dernier message: 21/01/2005, 13h29
  3. Comment développer un projet à plusieurs ?
    Par Clandestino dans le forum Outils
    Réponses: 7
    Dernier message: 07/01/2005, 08h29
  4. Comment cloner un dataset en delphi
    Par laurent82 dans le forum Bases de données
    Réponses: 2
    Dernier message: 18/06/2004, 10h41

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